1 use std::iter; 2 use std::mem; 3 use std::slice; 4 5 /// A single URL parameter, consisting of a key and a value. 6 #[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Default, Copy, Clone)] 7 struct Param<'k, 'v> { 8 key: &'k [u8], 9 value: &'v [u8], 10 } 11 12 impl<'k, 'v> Param<'k, 'v> { 13 // this could be from_utf8_unchecked, but we'll keep this safe for now key_str(&self) -> &'k str14 fn key_str(&self) -> &'k str { 15 std::str::from_utf8(self.key).unwrap() 16 } 17 value_str(&self) -> &'v str18 fn value_str(&self) -> &'v str { 19 std::str::from_utf8(self.value).unwrap() 20 } 21 } 22 23 /// A list of parameters returned by a route match. 24 /// 25 /// ```rust 26 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 27 /// # let mut router = matchit::Router::new(); 28 /// # router.insert("/users/:id", true).unwrap(); 29 /// let matched = router.at("/users/1")?; 30 /// 31 /// // you can iterate through the keys and values 32 /// for (key, value) in matched.params.iter() { 33 /// println!("key: {}, value: {}", key, value); 34 /// } 35 /// 36 /// // or get a specific value by key 37 /// let id = matched.params.get("id"); 38 /// assert_eq!(id, Some("1")); 39 /// # Ok(()) 40 /// # } 41 /// ``` 42 #[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)] 43 pub struct Params<'k, 'v> { 44 kind: ParamsKind<'k, 'v>, 45 } 46 47 // most routes have 1-3 dynamic parameters, so we can avoid a heap allocation in common cases. 48 const SMALL: usize = 3; 49 50 #[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)] 51 enum ParamsKind<'k, 'v> { 52 None, 53 Small([Param<'k, 'v>; SMALL], usize), 54 Large(Vec<Param<'k, 'v>>), 55 } 56 57 impl<'k, 'v> Params<'k, 'v> { new() -> Self58 pub(crate) fn new() -> Self { 59 let kind = ParamsKind::None; 60 Self { kind } 61 } 62 63 /// Returns the number of parameters. len(&self) -> usize64 pub fn len(&self) -> usize { 65 match &self.kind { 66 ParamsKind::None => 0, 67 ParamsKind::Small(_, len) => *len, 68 ParamsKind::Large(vec) => vec.len(), 69 } 70 } 71 truncate(&mut self, n: usize)72 pub(crate) fn truncate(&mut self, n: usize) { 73 match &mut self.kind { 74 ParamsKind::None => {} 75 ParamsKind::Small(_, len) => { 76 *len = n; 77 } 78 ParamsKind::Large(vec) => { 79 vec.truncate(n); 80 } 81 } 82 } 83 84 /// Returns the value of the first parameter registered under the given key. get(&self, key: impl AsRef<str>) -> Option<&'v str>85 pub fn get(&self, key: impl AsRef<str>) -> Option<&'v str> { 86 let key = key.as_ref().as_bytes(); 87 88 match &self.kind { 89 ParamsKind::None => None, 90 ParamsKind::Small(arr, len) => arr 91 .iter() 92 .take(*len) 93 .find(|param| param.key == key) 94 .map(Param::value_str), 95 ParamsKind::Large(vec) => vec 96 .iter() 97 .find(|param| param.key == key) 98 .map(Param::value_str), 99 } 100 } 101 102 /// Returns an iterator over the parameters in the list. iter(&self) -> ParamsIter<'_, 'k, 'v>103 pub fn iter(&self) -> ParamsIter<'_, 'k, 'v> { 104 ParamsIter::new(self) 105 } 106 107 /// Returns `true` if there are no parameters in the list. is_empty(&self) -> bool108 pub fn is_empty(&self) -> bool { 109 match &self.kind { 110 ParamsKind::None => true, 111 ParamsKind::Small(_, len) => *len == 0, 112 ParamsKind::Large(vec) => vec.is_empty(), 113 } 114 } 115 116 /// Inserts a key value parameter pair into the list. push(&mut self, key: &'k [u8], value: &'v [u8])117 pub(crate) fn push(&mut self, key: &'k [u8], value: &'v [u8]) { 118 #[cold] 119 fn drain_to_vec<T: Default>(len: usize, elem: T, arr: &mut [T; SMALL]) -> Vec<T> { 120 let mut vec = Vec::with_capacity(len + 1); 121 vec.extend(arr.iter_mut().map(mem::take)); 122 vec.push(elem); 123 vec 124 } 125 126 let param = Param { key, value }; 127 match &mut self.kind { 128 ParamsKind::None => { 129 self.kind = ParamsKind::Small([param, Param::default(), Param::default()], 1); 130 } 131 ParamsKind::Small(arr, len) => { 132 if *len == SMALL { 133 self.kind = ParamsKind::Large(drain_to_vec(*len, param, arr)); 134 return; 135 } 136 arr[*len] = param; 137 *len += 1; 138 } 139 ParamsKind::Large(vec) => vec.push(param), 140 } 141 } 142 143 // Transform each key. for_each_key_mut(&mut self, f: impl Fn((usize, &mut &'k [u8])))144 pub(crate) fn for_each_key_mut(&mut self, f: impl Fn((usize, &mut &'k [u8]))) { 145 match &mut self.kind { 146 ParamsKind::None => {} 147 ParamsKind::Small(arr, len) => arr 148 .iter_mut() 149 .take(*len) 150 .map(|param| &mut param.key) 151 .enumerate() 152 .for_each(f), 153 ParamsKind::Large(vec) => vec 154 .iter_mut() 155 .map(|param| &mut param.key) 156 .enumerate() 157 .for_each(f), 158 } 159 } 160 } 161 162 /// An iterator over the keys and values of a route's [parameters](crate::Params). 163 pub struct ParamsIter<'ps, 'k, 'v> { 164 kind: ParamsIterKind<'ps, 'k, 'v>, 165 } 166 167 impl<'ps, 'k, 'v> ParamsIter<'ps, 'k, 'v> { new(params: &'ps Params<'k, 'v>) -> Self168 fn new(params: &'ps Params<'k, 'v>) -> Self { 169 let kind = match ¶ms.kind { 170 ParamsKind::None => ParamsIterKind::None, 171 ParamsKind::Small(arr, len) => ParamsIterKind::Small(arr.iter().take(*len)), 172 ParamsKind::Large(vec) => ParamsIterKind::Large(vec.iter()), 173 }; 174 Self { kind } 175 } 176 } 177 178 enum ParamsIterKind<'ps, 'k, 'v> { 179 None, 180 Small(iter::Take<slice::Iter<'ps, Param<'k, 'v>>>), 181 Large(slice::Iter<'ps, Param<'k, 'v>>), 182 } 183 184 impl<'ps, 'k, 'v> Iterator for ParamsIter<'ps, 'k, 'v> { 185 type Item = (&'k str, &'v str); 186 next(&mut self) -> Option<Self::Item>187 fn next(&mut self) -> Option<Self::Item> { 188 match self.kind { 189 ParamsIterKind::None => None, 190 ParamsIterKind::Small(ref mut iter) => { 191 iter.next().map(|p| (p.key_str(), p.value_str())) 192 } 193 ParamsIterKind::Large(ref mut iter) => { 194 iter.next().map(|p| (p.key_str(), p.value_str())) 195 } 196 } 197 } 198 } 199 200 #[cfg(test)] 201 mod tests { 202 use super::*; 203 204 #[test] no_alloc()205 fn no_alloc() { 206 assert_eq!(Params::new().kind, ParamsKind::None); 207 } 208 209 #[test] heap_alloc()210 fn heap_alloc() { 211 let vec = vec![ 212 ("hello", "hello"), 213 ("world", "world"), 214 ("foo", "foo"), 215 ("bar", "bar"), 216 ("baz", "baz"), 217 ]; 218 219 let mut params = Params::new(); 220 for (key, value) in vec.clone() { 221 params.push(key.as_bytes(), value.as_bytes()); 222 assert_eq!(params.get(key), Some(value)); 223 } 224 225 match params.kind { 226 ParamsKind::Large(..) => {} 227 _ => panic!(), 228 } 229 230 assert!(params.iter().eq(vec.clone())); 231 } 232 233 #[test] stack_alloc()234 fn stack_alloc() { 235 let vec = vec![("hello", "hello"), ("world", "world"), ("baz", "baz")]; 236 237 let mut params = Params::new(); 238 for (key, value) in vec.clone() { 239 params.push(key.as_bytes(), value.as_bytes()); 240 assert_eq!(params.get(key), Some(value)); 241 } 242 243 match params.kind { 244 ParamsKind::Small(..) => {} 245 _ => panic!(), 246 } 247 248 assert!(params.iter().eq(vec.clone())); 249 } 250 251 #[test] ignore_array_default()252 fn ignore_array_default() { 253 let params = Params::new(); 254 assert!(params.get("").is_none()); 255 } 256 } 257