serde_html_form/
de.rs

1//! Deserialization support for the `application/x-www-form-urlencoded` format.
2
3use std::io::Read;
4
5use form_urlencoded::{parse, Parse as UrlEncodedParse};
6use indexmap::map::{self, IndexMap};
7use serde::{
8    de::{self, value::MapDeserializer},
9    forward_to_deserialize_any,
10};
11
12#[doc(inline)]
13pub use serde::de::value::Error;
14
15mod part;
16mod val_or_vec;
17
18use self::{part::Part, val_or_vec::ValOrVec};
19
20/// Deserializes a `application/x-www-form-urlencoded` value from a `&[u8]`.
21///
22/// ```
23/// let meal = vec![
24///     ("bread".to_owned(), "baguette".to_owned()),
25///     ("cheese".to_owned(), "comté".to_owned()),
26///     ("meat".to_owned(), "ham".to_owned()),
27///     ("fat".to_owned(), "butter".to_owned()),
28/// ];
29///
30/// assert_eq!(
31///     serde_html_form::from_bytes::<Vec<(String, String)>>(
32///         b"bread=baguette&cheese=comt%C3%A9&meat=ham&fat=butter"
33///     ),
34///     Ok(meal)
35/// );
36/// ```
37pub fn from_bytes<'de, T>(input: &'de [u8]) -> Result<T, Error>
38where
39    T: de::Deserialize<'de>,
40{
41    T::deserialize(Deserializer::new(parse(input)))
42}
43
44/// Deserializes a `application/x-www-form-urlencoded` value from a `&str`.
45///
46/// ```
47/// let meal = vec![
48///     ("bread".to_owned(), "baguette".to_owned()),
49///     ("cheese".to_owned(), "comté".to_owned()),
50///     ("meat".to_owned(), "ham".to_owned()),
51///     ("fat".to_owned(), "butter".to_owned()),
52/// ];
53///
54/// assert_eq!(
55///     serde_html_form::from_str::<Vec<(String, String)>>(
56///         "bread=baguette&cheese=comt%C3%A9&meat=ham&fat=butter"
57///     ),
58///     Ok(meal)
59/// );
60/// ```
61pub fn from_str<'de, T>(input: &'de str) -> Result<T, Error>
62where
63    T: de::Deserialize<'de>,
64{
65    from_bytes(input.as_bytes())
66}
67
68/// Convenience function that reads all bytes from `reader` and deserializes
69/// them with `from_bytes`.
70pub fn from_reader<T, R>(mut reader: R) -> Result<T, Error>
71where
72    T: de::DeserializeOwned,
73    R: Read,
74{
75    let mut buf = vec![];
76    reader
77        .read_to_end(&mut buf)
78        .map_err(|e| de::Error::custom(format_args!("could not read input: {}", e)))?;
79    from_bytes(&buf)
80}
81
82/// A deserializer for the `application/x-www-form-urlencoded` format.
83///
84/// * Supported top-level outputs are structs, maps and sequences of pairs,
85///   with or without a given length.
86///
87/// * Main `deserialize` methods defers to `deserialize_map`.
88///
89/// * Everything else but `deserialize_seq` and `deserialize_seq_fixed_size`
90///   defers to `deserialize`.
91pub struct Deserializer<'de> {
92    inner: UrlEncodedParse<'de>,
93}
94
95impl<'de> Deserializer<'de> {
96    /// Returns a new `Deserializer`.
97    pub fn new(parse: UrlEncodedParse<'de>) -> Self {
98        Deserializer { inner: parse }
99    }
100}
101
102impl<'de> de::Deserializer<'de> for Deserializer<'de> {
103    type Error = Error;
104
105    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
106    where
107        V: de::Visitor<'de>,
108    {
109        self.deserialize_seq(visitor)
110    }
111
112    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
113    where
114        V: de::Visitor<'de>,
115    {
116        visitor.visit_map(MapDeserializer::new(group_entries(self.inner).into_iter()))
117    }
118
119    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
120    where
121        V: de::Visitor<'de>,
122    {
123        visitor.visit_seq(MapDeserializer::new(PartIterator(self.inner)))
124    }
125
126    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
127    where
128        V: de::Visitor<'de>,
129    {
130        let deserializer = MapDeserializer::new(PartIterator(self.inner));
131        deserializer.end()?;
132        visitor.visit_unit()
133    }
134
135    fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
136    where
137        V: de::Visitor<'de>,
138    {
139        visitor.visit_newtype_struct(self)
140    }
141
142    fn deserialize_struct<V>(
143        self,
144        _name: &'static str,
145        _fields: &'static [&'static str],
146        visitor: V,
147    ) -> Result<V::Value, Self::Error>
148    where
149        V: de::Visitor<'de>,
150    {
151        self.deserialize_map(visitor)
152    }
153
154    forward_to_deserialize_any! {
155        bool
156        u8
157        u16
158        u32
159        u64
160        i8
161        i16
162        i32
163        i64
164        f32
165        f64
166        char
167        str
168        string
169        option
170        bytes
171        byte_buf
172        unit_struct
173        tuple_struct
174        identifier
175        tuple
176        enum
177        ignored_any
178    }
179}
180
181struct PartIterator<'de>(UrlEncodedParse<'de>);
182
183impl<'de> Iterator for PartIterator<'de> {
184    type Item = (Part<'de>, Part<'de>);
185
186    fn next(&mut self) -> Option<Self::Item> {
187        self.0.next().map(|(k, v)| (Part(k), Part(v)))
188    }
189}
190
191fn group_entries(parse: UrlEncodedParse<'_>) -> IndexMap<Part<'_>, ValOrVec<Part<'_>>> {
192    use map::Entry::*;
193
194    let mut res = IndexMap::new();
195
196    for (key, value) in parse {
197        match res.entry(Part(key)) {
198            Vacant(v) => {
199                v.insert(ValOrVec::Val(Part(value)));
200            }
201            Occupied(mut o) => {
202                o.get_mut().push(Part(value));
203            }
204        }
205    }
206
207    res
208}
209
210#[cfg(test)]
211mod tests;