serde_querystring/parsers/
duplicate.rs

1use std::{borrow::Cow, collections::BTreeMap};
2
3use crate::decode::{parse_bytes, Reference};
4
5struct Key<'a>(&'a [u8]);
6
7impl<'a> Key<'a> {
8    fn parse(slice: &'a [u8]) -> Self {
9        let mut index = 0;
10        while index < slice.len() {
11            match slice[index] {
12                b'&' | b'=' => break,
13                _ => index += 1,
14            }
15        }
16
17        Self(&slice[..index])
18    }
19
20    fn len(&self) -> usize {
21        self.0.len()
22    }
23
24    fn decode<'s>(&self, scratch: &'s mut Vec<u8>) -> Reference<'a, 's, [u8]> {
25        parse_bytes(self.0, scratch)
26    }
27}
28
29struct Value<'a>(&'a [u8]);
30
31impl<'a> Value<'a> {
32    fn parse(slice: &'a [u8]) -> Option<Self> {
33        if *slice.first()? == b'&' {
34            return None;
35        }
36
37        let mut index = 1;
38        while index < slice.len() {
39            match slice[index] {
40                b'&' => break,
41                _ => index += 1,
42            }
43        }
44
45        Some(Self(&slice[1..index]))
46    }
47
48    fn len(&self) -> usize {
49        self.0.len()
50    }
51
52    fn decode<'s>(&self, scratch: &'s mut Vec<u8>) -> Reference<'a, 's, [u8]> {
53        parse_bytes(self.0, scratch)
54    }
55
56    fn slice(&self) -> &'a [u8] {
57        self.0
58    }
59}
60
61struct Pair<'a>(Key<'a>, Option<Value<'a>>);
62
63impl<'a> Pair<'a> {
64    fn parse(slice: &'a [u8]) -> Self {
65        let key = Key::parse(slice);
66        let value = Value::parse(&slice[key.len()..]);
67
68        Self(key, value)
69    }
70
71    /// It report how many chars we should move forward after this pair, to see a new one.
72    /// It might report invalid result at the end of the slice,
73    /// so calling site should check the validity of resulting index
74    fn skip_len(&self) -> usize {
75        match &self.1 {
76            Some(v) => self.0.len() + v.len() + 2,
77            None => self.0.len() + 1,
78        }
79    }
80}
81
82/// A querystring parser with support for vectors/lists of values by repeating keys.
83///
84/// # Note
85/// Keys are decoded when calling the `parse` method, but values are lazily decoded when you
86/// call the `value` method for their keys.
87///
88/// # Example
89/// ```rust
90///# use std::borrow::Cow;
91/// use serde_querystring::DuplicateQS;
92///
93/// let slice = b"foo=bar&foo=baz&foo&foo=";
94///
95/// let parser = DuplicateQS::parse(slice);
96///
97/// // `values` method returns ALL the values as a vector.
98/// assert_eq!(
99///    parser.values(b"foo"),
100///    Some(vec![
101///        Some("bar".as_bytes().into()),
102///        Some("baz".as_bytes().into()),
103///        None,
104///        Some("".as_bytes().into())
105///    ])
106///);
107///
108/// // `value` method returns the last seen value
109/// assert_eq!(parser.value(b"foo"), Some(Some("".as_bytes().into())));
110/// ```
111pub struct DuplicateQS<'a> {
112    pairs: BTreeMap<Cow<'a, [u8]>, Vec<Pair<'a>>>,
113}
114
115impl<'a> DuplicateQS<'a> {
116    /// Parse a slice of bytes into a `DuplicateQS`
117    pub fn parse(slice: &'a [u8]) -> Self {
118        let mut pairs: BTreeMap<Cow<'a, [u8]>, Vec<Pair<'a>>> = BTreeMap::new();
119        let mut scratch = Vec::new();
120
121        let mut index = 0;
122
123        while index < slice.len() {
124            let pair = Pair::parse(&slice[index..]);
125            index += pair.skip_len();
126
127            let decoded_key = pair.0.decode(&mut scratch);
128
129            if let Some(values) = pairs.get_mut(decoded_key.as_ref()) {
130                values.push(pair);
131            } else {
132                pairs.insert(decoded_key.into_cow(), vec![pair]);
133            }
134        }
135
136        Self { pairs }
137    }
138
139    /// Returns a vector containing all the keys in querystring.
140    pub fn keys(&self) -> Vec<&Cow<'a, [u8]>> {
141        self.pairs.keys().collect()
142    }
143
144    /// Returns a vector containing all the values assigned to a key.
145    ///
146    /// It returns None if the **key doesn't exist** in the querystring,
147    /// the resulting vector may contain None if the **key had assignments without a value**, ex `&key&`
148    ///
149    /// # Note
150    /// Percent decoding the value is done on-the-fly **every time** this function is called.
151    pub fn values(&self, key: &'a [u8]) -> Option<Vec<Option<Cow<'a, [u8]>>>> {
152        let mut scratch = Vec::new();
153
154        Some(
155            self.pairs
156                .get(key)?
157                .iter()
158                .map(|p| p.1.as_ref().map(|v| v.decode(&mut scratch).into_cow()))
159                .collect(),
160        )
161    }
162
163    /// Returns the last value assigned to a key.
164    ///
165    /// It returns `None` if the **key doesn't exist** in the querystring,
166    /// and returns `Some(None)` if the last assignment to a **key doesn't have a value**, ex `"&key&"`
167    ///
168    /// # Note
169    /// Percent decoding the value is done on-the-fly **every time** this function is called.
170    pub fn value(&self, key: &'a [u8]) -> Option<Option<Cow<'a, [u8]>>> {
171        let mut scratch = Vec::new();
172
173        self.pairs
174            .get(key)?
175            .iter()
176            .last()
177            .map(|p| p.1.as_ref().map(|v| v.decode(&mut scratch).into_cow()))
178    }
179}
180
181#[cfg(feature = "serde")]
182mod de {
183    use _serde::Deserialize;
184
185    use crate::de::{
186        Error, ErrorKind, QSDeserializer,
187        __implementors::{DecodedSlice, IntoRawSlices, RawSlice},
188    };
189
190    use super::DuplicateQS;
191
192    impl<'a> DuplicateQS<'a> {
193        /// Deserialize the parsed slice into T
194        pub fn deserialize<T: Deserialize<'a>>(self) -> Result<T, Error> {
195            T::deserialize(QSDeserializer::new(self.into_iter()))
196        }
197
198        pub(crate) fn into_iter(
199            self,
200        ) -> impl Iterator<
201            Item = (
202                DecodedSlice<'a>,
203                DuplicateValueIter<impl Iterator<Item = RawSlice<'a>>>,
204            ),
205        > {
206            self.pairs.into_iter().map(|(key, pairs)| {
207                (
208                    DecodedSlice(key),
209                    DuplicateValueIter(
210                        pairs
211                            .into_iter()
212                            .map(|v| RawSlice(v.1.map(|v| v.slice()).unwrap_or_default())),
213                    ),
214                )
215            })
216        }
217    }
218
219    pub(crate) struct DuplicateValueIter<I>(I);
220
221    impl<'a, I> IntoRawSlices<'a> for DuplicateValueIter<I>
222    where
223        I: Iterator<Item = RawSlice<'a>>,
224    {
225        type SizedIterator = I;
226        type UnSizedIterator = I;
227
228        #[inline]
229        fn into_sized_iterator(self, size: usize) -> Result<I, Error> {
230            if self.0.size_hint().0 == size {
231                Ok(self.0)
232            } else {
233                Err(Error::new(ErrorKind::InvalidLength))
234            }
235        }
236
237        #[inline]
238        fn into_unsized_iterator(self) -> I {
239            self.0
240        }
241
242        #[inline]
243        fn into_single_slice(self) -> RawSlice<'a> {
244            self.0
245                .last()
246                .expect("Iterator has at least one value in it")
247        }
248    }
249}
250
251#[cfg(test)]
252mod tests {
253    use std::borrow::Cow;
254
255    use super::DuplicateQS;
256
257    #[test]
258    fn parse_pair() {
259        let slice = b"key=value";
260
261        let parser = DuplicateQS::parse(slice);
262
263        assert_eq!(parser.keys(), vec![&Cow::Borrowed(b"key")]);
264        assert_eq!(
265            parser.values(b"key"),
266            Some(vec![Some(Cow::Borrowed("value".as_bytes()))])
267        );
268        assert_eq!(
269            parser.value(b"key"),
270            Some(Some(Cow::Borrowed("value".as_bytes())))
271        );
272    }
273
274    #[test]
275    fn parse_multiple_pairs() {
276        let slice = b"foo=bar&foobar=baz&qux=box";
277
278        let parser = DuplicateQS::parse(slice);
279
280        assert_eq!(
281            parser.values(b"foo"),
282            Some(vec![Some("bar".as_bytes().into())])
283        );
284        assert_eq!(
285            parser.values(b"foobar"),
286            Some(vec![Some("baz".as_bytes().into())])
287        );
288        assert_eq!(
289            parser.values(b"qux"),
290            Some(vec![Some("box".as_bytes().into())])
291        );
292    }
293
294    #[test]
295    fn parse_no_value() {
296        let slice = b"foo&foobar=";
297
298        let parser = DuplicateQS::parse(slice);
299
300        assert_eq!(parser.value(b"key"), None);
301        assert_eq!(parser.values(b"key"), None);
302        assert_eq!(parser.value(b"foo"), Some(None));
303        assert_eq!(parser.values(b"foo"), Some(vec![None]));
304        assert_eq!(
305            parser.values(b"foobar"),
306            Some(vec![Some("".as_bytes().into())])
307        );
308        assert_eq!(parser.value(b"foobar"), Some(Some("".as_bytes().into())));
309    }
310
311    #[test]
312    fn parse_multiple_values() {
313        let slice = b"foo=bar&foo=baz&foo=foobar&foo&foo=";
314
315        let parser = DuplicateQS::parse(slice);
316
317        assert_eq!(
318            parser.values(b"foo"),
319            Some(vec![
320                Some("bar".as_bytes().into()),
321                Some("baz".as_bytes().into()),
322                Some("foobar".as_bytes().into()),
323                None,
324                Some("".as_bytes().into())
325            ])
326        );
327
328        assert_eq!(parser.value(b"foo"), Some(Some("".as_bytes().into())));
329    }
330}