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::from_bytes(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    /// Returns a new `Deserializer` from a `&[u8]`.
102    pub fn from_bytes(input: &'de [u8]) -> Self {
103        Self::new(parse(input))
104    }
105}
106
107impl<'de> de::Deserializer<'de> for Deserializer<'de> {
108    type Error = Error;
109
110    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
111    where
112        V: de::Visitor<'de>,
113    {
114        self.deserialize_seq(visitor)
115    }
116
117    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
118    where
119        V: de::Visitor<'de>,
120    {
121        visitor.visit_map(MapDeserializer::new(group_entries(self.inner).into_iter()))
122    }
123
124    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
125    where
126        V: de::Visitor<'de>,
127    {
128        visitor.visit_seq(MapDeserializer::new(PartIterator(self.inner)))
129    }
130
131    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
132    where
133        V: de::Visitor<'de>,
134    {
135        let deserializer = MapDeserializer::new(PartIterator(self.inner));
136        deserializer.end()?;
137        visitor.visit_unit()
138    }
139
140    fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
141    where
142        V: de::Visitor<'de>,
143    {
144        visitor.visit_newtype_struct(self)
145    }
146
147    fn deserialize_struct<V>(
148        self,
149        _name: &'static str,
150        _fields: &'static [&'static str],
151        visitor: V,
152    ) -> Result<V::Value, Self::Error>
153    where
154        V: de::Visitor<'de>,
155    {
156        self.deserialize_map(visitor)
157    }
158
159    forward_to_deserialize_any! {
160        bool
161        u8
162        u16
163        u32
164        u64
165        i8
166        i16
167        i32
168        i64
169        f32
170        f64
171        char
172        str
173        string
174        option
175        bytes
176        byte_buf
177        unit_struct
178        tuple_struct
179        identifier
180        tuple
181        enum
182        ignored_any
183    }
184}
185
186struct PartIterator<'de>(UrlEncodedParse<'de>);
187
188impl<'de> Iterator for PartIterator<'de> {
189    type Item = (Part<'de>, Part<'de>);
190
191    fn next(&mut self) -> Option<Self::Item> {
192        self.0.next().map(|(k, v)| (Part(k), Part(v)))
193    }
194}
195
196fn group_entries(parse: UrlEncodedParse<'_>) -> IndexMap<Part<'_>, ValOrVec<Part<'_>>> {
197    use map::Entry::*;
198
199    let mut res = IndexMap::new();
200
201    for (key, value) in parse {
202        match res.entry(Part(key)) {
203            Vacant(v) => {
204                v.insert(ValOrVec::Val(Part(value)));
205            }
206            Occupied(mut o) => {
207                o.get_mut().push(Part(value));
208            }
209        }
210    }
211
212    res
213}
214
215#[cfg(test)]
216mod tests;