oauth1_request/serializer/
urlencode.rs

1//! A URI query/`x-www-form-urlencoded` string serializer.
2
3use core::fmt::Write;
4
5use crate::util::PercentEncode;
6
7use super::Serializer;
8
9cfg_type_param_hack! {
10    /// A `Serializer` that produces a URI query or an `x-www-form-urlencoded` string from a
11    /// request.
12    #[derive(Clone, Debug)]
13    pub struct Urlencoder<
14        #[cfg(feature = "alloc")] W = alloc::string::String,
15        #[cfg(not(feature = "alloc"))] W,
16    > {
17        data: W,
18        next_append: Append,
19    }
20}
21
22#[derive(Clone, Debug)]
23enum Append {
24    None,
25    Question,
26    Ampersand,
27}
28
29doc_auto_cfg! {
30    #[cfg(feature = "alloc")]
31    impl Urlencoder {
32        /// Creates a `Urlencoder` that produces an `x-www-form-urlencoded` string.
33        pub fn form() -> Self {
34            Urlencoder {
35                data: alloc::string::String::new(),
36                next_append: Append::None,
37            }
38        }
39    }
40}
41
42impl<W> Urlencoder<W>
43where
44    W: Write,
45{
46    /// Same with `form` but writes the resulting form string into `buf`.
47    pub fn form_with_buf(buf: W) -> Self {
48        Urlencoder {
49            data: buf,
50            next_append: Append::None,
51        }
52    }
53
54    /// Creates a `Urlencoder` that appends a query part to the given URI.
55    pub fn query(uri: W) -> Self {
56        Urlencoder {
57            data: uri,
58            next_append: Append::Question,
59        }
60    }
61
62    fn append_delim(&mut self) {
63        match self.next_append {
64            Append::None => self.next_append = Append::Ampersand,
65            Append::Question => {
66                self.data.write_char('?').unwrap();
67                self.next_append = Append::Ampersand;
68            }
69            Append::Ampersand => self.data.write_char('&').unwrap(),
70        }
71    }
72}
73
74impl<W: Write> Serializer for Urlencoder<W> {
75    type Output = W;
76
77    fn serialize_parameter<V>(&mut self, key: &str, value: V)
78    where
79        V: core::fmt::Display,
80    {
81        self.append_delim();
82        write!(self.data, "{}={}", key, PercentEncode(&value)).unwrap();
83    }
84
85    fn serialize_parameter_encoded<V>(&mut self, key: &str, value: V)
86    where
87        V: core::fmt::Display,
88    {
89        self.append_delim();
90        write!(self.data, "{}={}", key, value).unwrap();
91    }
92
93    super::skip_serialize_oauth_parameters!();
94
95    fn end(self) -> Self::Output {
96        self.data
97    }
98}