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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
//! Matchers used to compare against incoming segments.
//!
//! Values of type `Matcher` are stored inside a tree and used to match
//! against incoming segments in order to walk through the tree correctly.
use crate::capture::Capture;
/// Matching trait to enable generic route matching algorithms.
///
/// This trait backs the main tree, enabling custom segment matching based
/// on the needs of the end developer. In many cases it's wasteful to check
/// for things like RegEx, especially when all routes will only be static
/// (as an example).
pub trait Matcher: Send + Sync {
/// Retrieves a potential capture from a segment.
fn capture<'a>(&'a self, _segment: &str) -> Option<Capture<'a>> {
None
}
/// Determines whether an incoming segment is a match for a base segment.
fn is_match(&self, segment: &str) -> bool;
}
/// Blanket implementation of `Matcher` for pure functions.
///
/// Pure functions are assumed to not have a capture group, as there's no
/// way to directly name them at this point (unless derived from the input).
impl<F> Matcher for F
where
F: Fn(&str) -> bool + Send + Sync,
{
/// Determines whether an incoming segment is a match for a base segment.
fn is_match(&self, segment: &str) -> bool {
self(segment)
}
}
/// Static path segment matcher.
///
/// This struct is constructed via the `StaticParser` and compares incoming
/// segments directly against the internal static `String` segment.
pub struct StaticMatcher {
inner: String,
}
impl StaticMatcher {
/// Constructs a new `StaticMatcher` from a segment.
pub fn new<S: Into<String>>(s: S) -> Self {
Self { inner: s.into() }
}
}
impl Matcher for StaticMatcher {
/// Compares an incoming segment against a literal base segment.
fn is_match(&self, segment: &str) -> bool {
self.inner == segment
}
}
/// Dynamic path segment matcher.
///
/// This struct is constructed via the `DynamicParser` and assumes that any
/// incoming path segment is a candidate for matching.
pub struct DynamicMatcher {
inner: String,
}
impl DynamicMatcher {
/// Constructs a new `DynamicMatcher` from a segment.
pub fn new<S: Into<String>>(s: S) -> Self {
Self { inner: s.into() }
}
}
impl Matcher for DynamicMatcher {
/// Determines if there is a capture for the incoming segment.
fn capture<'a>(&'a self, segment: &str) -> Option<Capture<'a>> {
Some((&self.inner, (0, segment.len())))
}
/// Determines if this matcher matches the incoming segment.
fn is_match(&self, _segment: &str) -> bool {
true
}
}