querystring_tiny/
querystring.rs

1//! Implements a trivial query string decoder
2
3use crate::error::Error;
4use std::{collections::BTreeMap, iter::FromIterator, ops::Deref};
5
6/// A query string
7///
8/// ## Warning
9/// The query parser is pretty simple and basically parses any `key` or `key=` or `key=value` component without further
10/// validation.
11///
12/// The following rules apply:
13///  - the query string _MUST NOT_ begin with a `?` – it's not a bug, it's a feature: this allows the parser to parse raw
14///    query strings in the body (e.g. from HTML forms)
15///  - keys don't need a value (i.e. `key0&key1` is valid)
16///  - keys can have an empty value (i.e. `key0=&key1=` is valid)
17///  - keys can have a non-empty value (i.e. `key0=value0&key1=value1` is valid)
18///  - empty keys/key-value pairs are ignored (i.e. `&` evaluates to `[]`, `key0&&key1` evaluates to
19///    `["key0": "", "key1": ""]` and `=value0&key1=value1&` evaluates to `["key1": "value1"]`)
20#[derive(Debug, Clone, Default)]
21pub struct QueryString {
22    /// The key-value fields of the query string
23    fields: BTreeMap<Vec<u8>, Vec<u8>>,
24}
25impl QueryString {
26    /// Creates a new header field map
27    pub fn new() -> Self {
28        Self { fields: BTreeMap::new() }
29    }
30    /// Decodes a query string
31    pub fn decode(source: &[u8]) -> Result<Self, Error> {
32        // Parse the query components
33        let (mut source, mut fields) = (source.iter().copied(), BTreeMap::new());
34        while source.len() > 0 {
35            // Read the next pair
36            let mut pair = (&mut source).take_while(|&b| b != b'&');
37            let key: Vec<_> = (&mut pair).take_while(|&b| b != b'=').collect();
38            let value: Vec<_> = (&mut pair).collect();
39
40            // Insert the key if it is not empty
41            if !key.is_empty() {
42                fields.insert(key, value);
43            }
44        }
45        Ok(Self { fields })
46    }
47
48    /// Gets the value for the field with the given name
49    pub fn get<T>(&self, name: T) -> Option<&[u8]>
50    where
51        T: AsRef<[u8]>,
52    {
53        self.fields.get(name.as_ref()).map(|s| s.as_ref())
54    }
55    /// Sets the value for a fiels with the given name
56    pub fn set<A, B>(&mut self, name: A, value: B)
57    where
58        A: Into<Vec<u8>>,
59        B: Into<Vec<u8>>,
60    {
61        self.fields.insert(name.into(), value.into());
62    }
63
64    /// Encodes the query string
65    pub fn encode(&self) -> Vec<u8> {
66        // Serialize all elements
67        let mut serialized = Vec::new();
68        for (key, value) in self.fields.iter() {
69            // Write delimiter
70            if !serialized.is_empty() {
71                serialized.extend(b"&");
72            }
73
74            // Write key and value
75            serialized.extend(key);
76            if !value.is_empty() {
77                serialized.extend(b"=");
78                serialized.extend(value);
79            }
80        }
81        serialized
82    }
83}
84impl Deref for QueryString {
85    type Target = BTreeMap<Vec<u8>, Vec<u8>>;
86
87    fn deref(&self) -> &Self::Target {
88        &self.fields
89    }
90}
91impl<K, V> FromIterator<(K, V)> for QueryString
92where
93    K: Into<Vec<u8>>,
94    V: Into<Vec<u8>>,
95{
96    fn from_iter<T: IntoIterator<Item = (K, V)>>(pairs: T) -> Self {
97        let fields = pairs.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
98        Self { fields }
99    }
100}
101impl IntoIterator for QueryString {
102    type Item = <BTreeMap<Vec<u8>, Vec<u8>> as IntoIterator>::Item;
103    type IntoIter = <BTreeMap<Vec<u8>, Vec<u8>> as IntoIterator>::IntoIter;
104
105    fn into_iter(self) -> Self::IntoIter {
106        self.fields.into_iter()
107    }
108}