1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
//! Defines helper functions for processing the request path
use crate::helpers::http::PercentDecoded;
const EXCLUDED_SEGMENTS: [&str; 1] = [""];
/// Holder for `Request` URI path segments that have been split into individual segments.
///
/// Used internally by the `Router` when traversing its internal `Tree`.
#[derive(Clone, Debug, PartialEq)]
pub struct RequestPathSegments {
segments: Vec<PercentDecoded>,
}
pub(crate) fn split_path_segments<'a>(path: &'a str) -> impl Iterator<Item = &'a str> {
path.split('/').filter(|s| !EXCLUDED_SEGMENTS.contains(s))
}
impl RequestPathSegments {
/// Creates a new RequestPathSegments instance by splitting a `Request` URI path.
///
/// Empty segments are skipped when generating the `RequestPathSegments` value, and a leading
/// `/` segment is added to represent the root (and the beginning of traversal). So, a request
/// path of `/some/path/to//my/handler` will be split into segments:
///
/// ```plain
/// ["/", "some", "path", "to", "my", "handler"]
/// ```
pub(crate) fn new(path: &str) -> Self {
let segments = split_path_segments(path)
.filter_map(PercentDecoded::new)
.collect();
RequestPathSegments { segments }
}
pub(crate) fn subsegments(&self, offset: usize) -> Self {
RequestPathSegments {
segments: self.segments.split_at(offset).1.to_vec(),
}
}
/// Provide segments that still need to be processed.
///
/// This will always include a "/" node to represent the root as well as all segments
/// that remain as of the current offset.
///
/// The offset starts at 0 meaning all segments of the initial Request path will be provided
/// until the offset is updated.
pub(crate) fn segments(&self) -> &Vec<PercentDecoded> {
&self.segments
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn request_path_segments_tests() {
// Validate the claim made in the doc comment above.
let rps = RequestPathSegments::new("/some/path/to//my/handler");
assert_eq!(
rps.segments.iter().map(AsRef::as_ref).collect::<Vec<_>>(),
vec!["some", "path", "to", "my", "handler"]
);
}
}