xitca_router/
params.rs

1use core::slice;
2
3use xitca_unsafe_collection::small_str::SmallBoxedStr;
4
5/// A single URL parameter, consisting of a key and a value.
6#[derive(Debug, PartialEq, Eq, Clone, Hash)]
7struct Param {
8    key: SmallBoxedStr,
9    value: SmallBoxedStr,
10}
11
12impl Param {
13    fn key_str(&self) -> &str {
14        self.key.as_ref()
15    }
16
17    fn value_str(&self) -> &str {
18        self.value.as_ref()
19    }
20}
21
22/// A list of parameters returned by a route match.
23///
24/// ```rust
25/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
26/// # let mut router = xitca_router::Router::new();
27/// # router.insert("/users/:id", true)?;
28/// let matched = router.at("/users/1")?;
29///
30/// // you can get a specific value by key
31/// let id = matched.params.get("id");
32/// assert_eq!(id, Some("1"));
33///
34/// // or iterate through the keys and values
35/// for (key, value) in matched.params.iter() {
36///     println!("key: {}, value: {}", key, value);
37/// }
38/// # Ok(())
39/// # }
40/// ```
41#[derive(Clone, Debug)]
42pub struct Params {
43    inner: Vec<Param>,
44}
45
46impl Default for Params {
47    fn default() -> Self {
48        Self::new()
49    }
50}
51
52impl Params {
53    /// Returns the number of parameters.
54    #[inline]
55    pub fn len(&self) -> usize {
56        self.inner.len()
57    }
58
59    /// Returns `true` if there are no parameters in the list.
60    #[inline]
61    pub fn is_empty(&self) -> bool {
62        self.len() == 0
63    }
64
65    /// Returns the value of the first parameter registered under the given key.
66    #[inline]
67    pub fn get(&self, key: impl AsRef<str>) -> Option<&str> {
68        self.inner
69            .iter()
70            .find(|param| param.key_str() == key.as_ref())
71            .map(Param::value_str)
72    }
73
74    #[inline]
75    pub fn iter(&self) -> Iter<'_> {
76        Iter {
77            inner: self.inner.iter(),
78        }
79    }
80}
81
82impl Params {
83    pub(super) const fn new() -> Self {
84        Self { inner: Vec::new() }
85    }
86
87    pub(super) fn truncate(&mut self, n: usize) {
88        self.inner.truncate(n)
89    }
90
91    pub(super) fn push(&mut self, key: &str, value: &str) {
92        self.inner.push(Param {
93            key: key.into(),
94            value: value.into(),
95        });
96    }
97
98    // Transform each key.
99    pub(crate) fn for_each_key_mut(&mut self, f: impl Fn((usize, &mut SmallBoxedStr))) {
100        self.inner
101            .iter_mut()
102            .map(|param| &mut param.key)
103            .enumerate()
104            .for_each(f);
105    }
106}
107
108impl IntoIterator for Params {
109    type Item = (SmallBoxedStr, SmallBoxedStr);
110    type IntoIter = IntoIter;
111
112    #[inline]
113    fn into_iter(self) -> Self::IntoIter {
114        IntoIter {
115            inner: self.inner.into_iter(),
116        }
117    }
118}
119
120pub struct Iter<'a> {
121    inner: slice::Iter<'a, Param>,
122}
123
124impl<'a> Iterator for Iter<'a> {
125    type Item = (&'a str, &'a str);
126
127    #[inline]
128    fn next(&mut self) -> Option<Self::Item> {
129        self.inner.next().map(|p| (p.key.as_ref(), p.value.as_ref()))
130    }
131
132    #[inline]
133    fn size_hint(&self) -> (usize, Option<usize>) {
134        self.inner.size_hint()
135    }
136}
137
138pub struct IntoIter {
139    inner: std::vec::IntoIter<Param>,
140}
141
142impl Iterator for IntoIter {
143    type Item = (SmallBoxedStr, SmallBoxedStr);
144
145    #[inline]
146    fn next(&mut self) -> Option<Self::Item> {
147        self.inner.next().map(|p| (p.key, p.value))
148    }
149
150    #[inline]
151    fn size_hint(&self) -> (usize, Option<usize>) {
152        self.inner.size_hint()
153    }
154}
155
156#[cfg(test)]
157mod tests {
158    use super::*;
159
160    #[test]
161    fn no_alloc() {
162        assert!(Params::new().is_empty());
163    }
164
165    #[test]
166    fn ignore_array_default() {
167        let params = Params::new();
168        assert!(params.get("").is_none());
169    }
170}