1 use crate::tree::Node; 2 use crate::{InsertError, MatchError, Params}; 3 4 /// A URL router. 5 /// 6 /// See [the crate documentation](crate) for details. 7 #[derive(Clone)] 8 #[cfg_attr(test, derive(Debug))] 9 pub struct Router<T> { 10 root: Node<T>, 11 } 12 13 impl<T> Default for Router<T> { default() -> Self14 fn default() -> Self { 15 Self { 16 root: Node::default(), 17 } 18 } 19 } 20 21 impl<T> Router<T> { 22 /// Construct a new router. new() -> Self23 pub fn new() -> Self { 24 Self::default() 25 } 26 27 /// Insert a route. 28 /// 29 /// # Examples 30 /// 31 /// ```rust 32 /// # use matchit::Router; 33 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 34 /// let mut router = Router::new(); 35 /// router.insert("/home", "Welcome!")?; 36 /// router.insert("/users/:id", "A User")?; 37 /// # Ok(()) 38 /// # } 39 /// ``` insert(&mut self, route: impl Into<String>, value: T) -> Result<(), InsertError>40 pub fn insert(&mut self, route: impl Into<String>, value: T) -> Result<(), InsertError> { 41 self.root.insert(route, value) 42 } 43 44 /// Tries to find a value in the router matching the given path. 45 /// 46 /// # Examples 47 /// 48 /// ```rust 49 /// # use matchit::Router; 50 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 51 /// let mut router = Router::new(); 52 /// router.insert("/home", "Welcome!")?; 53 /// 54 /// let matched = router.at("/home").unwrap(); 55 /// assert_eq!(*matched.value, "Welcome!"); 56 /// # Ok(()) 57 /// # } 58 /// ``` at<'m, 'p>(&'m self, path: &'p str) -> Result<Match<'m, 'p, &'m T>, MatchError>59 pub fn at<'m, 'p>(&'m self, path: &'p str) -> Result<Match<'m, 'p, &'m T>, MatchError> { 60 match self.root.at(path.as_bytes()) { 61 Ok((value, params)) => Ok(Match { 62 // SAFETY: We only expose &mut T through &mut self 63 value: unsafe { &*value.get() }, 64 params, 65 }), 66 Err(e) => Err(e), 67 } 68 } 69 70 /// Tries to find a value in the router matching the given path, 71 /// returning a mutable reference. 72 /// 73 /// # Examples 74 /// 75 /// ```rust 76 /// # use matchit::Router; 77 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 78 /// let mut router = Router::new(); 79 /// router.insert("/", 1)?; 80 /// 81 /// *router.at_mut("/").unwrap().value += 1; 82 /// assert_eq!(*router.at("/").unwrap().value, 2); 83 /// # Ok(()) 84 /// # } 85 /// ``` at_mut<'m, 'p>( &'m mut self, path: &'p str, ) -> Result<Match<'m, 'p, &'m mut T>, MatchError>86 pub fn at_mut<'m, 'p>( 87 &'m mut self, 88 path: &'p str, 89 ) -> Result<Match<'m, 'p, &'m mut T>, MatchError> { 90 match self.root.at(path.as_bytes()) { 91 Ok((value, params)) => Ok(Match { 92 // SAFETY: We have &mut self 93 value: unsafe { &mut *value.get() }, 94 params, 95 }), 96 Err(e) => Err(e), 97 } 98 } 99 100 #[cfg(feature = "__test_helpers")] check_priorities(&self) -> Result<u32, (u32, u32)>101 pub fn check_priorities(&self) -> Result<u32, (u32, u32)> { 102 self.root.check_priorities() 103 } 104 } 105 106 /// A successful match consisting of the registered value 107 /// and URL parameters, returned by [`Router::at`](Router::at). 108 #[derive(Debug)] 109 pub struct Match<'k, 'v, V> { 110 /// The value stored under the matched node. 111 pub value: V, 112 /// The route parameters. See [parameters](crate#parameters) for more details. 113 pub params: Params<'k, 'v>, 114 } 115