Skip to main content

serde_qs/
ser.rs

1//! Serialization support for querystrings.
2
3mod encode;
4
5use encode::encode;
6
7use serde::ser;
8
9use crate::error::*;
10
11use std::fmt::Display;
12use std::io::Write;
13use std::str;
14
15/// Serializes a value into a querystring.
16///
17/// ```
18/// # use serde::{Deserialize, Serialize};
19/// #[derive(Deserialize, Serialize)]
20/// struct Query {
21///     name: String,
22///     age: u8,
23///     occupation: String,
24/// }
25///
26/// let q =  Query {
27///     name: "Alice".to_owned(),
28///     age: 24,
29///     occupation: "Student".to_owned(),
30/// };
31///
32///
33/// assert_eq!(
34///     serde_qs::to_string(&q).unwrap(),
35///     "name=Alice&age=24&occupation=Student");
36/// ```
37pub fn to_string<T: ser::Serialize>(input: &T) -> Result<String> {
38    let config = crate::Config::default();
39    config.serialize_string(input)
40}
41
42/// Serializes a value into a generic writer object.
43///
44/// ```
45/// # use serde::{Deserialize, Serialize};
46/// #[derive(Deserialize, Serialize)]
47/// struct Query {
48///     name: String,
49///     age: u8,
50///     occupation: String,
51/// }
52///
53/// let q =  Query {
54///     name: "Alice".to_owned(),
55///     age: 24,
56///     occupation: "Student".to_owned(),
57/// };
58///
59/// let mut buffer = Vec::new();
60/// serde_qs::to_writer(&q, &mut buffer).unwrap();
61/// assert_eq!(
62///     String::from_utf8(buffer).unwrap(),
63///     "name=Alice&age=24&occupation=Student");
64/// ```
65pub fn to_writer<T: ser::Serialize, W: Write>(input: &T, writer: &mut W) -> Result<()> {
66    let config = crate::Config::default();
67    config.serialize_to_writer(input, writer)
68}
69
70/// A serializer for the querystring format.
71///
72/// This serializer converts Rust data structures into URL-encoded querystrings
73/// with support for nested structures using bracket notation.
74///
75/// ## Key Features
76///
77/// * **Nested structures**: Serializes nested objects as `parent[child]=value`
78/// * **Arrays**: Serializes sequences with indices like `items[0]=a&items[1]=b`
79/// * **Type support**: Handles primitives, strings, structs, maps, and sequences
80/// * **Encoding modes**: Supports both query-string and form encoding
81///
82/// ## Implementation Details
83///
84/// The serializer maintains a key stack to build nested paths. For example,
85/// when serializing `{user: {name: "John"}}`, it pushes "user" onto the stack,
86/// then serializes "name" as `user[name]=John`.
87pub struct QsSerializer<W: Write> {
88    writer: W,
89    first_kv: bool,
90    key: Vec<Vec<u8>>,
91    config: crate::Config,
92}
93
94impl<W: Write> QsSerializer<W> {
95    /// Creates a new `QsSerializer` with the given writer.
96    pub fn new(writer: W, config: crate::Config) -> Self {
97        Self {
98            writer,
99            first_kv: true,
100            key: Vec::with_capacity(4),
101            config,
102        }
103    }
104}
105
106impl<W: Write> QsSerializer<W> {
107    /// Pushes a new key segment onto the key stack for nested structures.
108    ///
109    /// This method builds the bracket notation for nested keys. For example:
110    /// - First key "user" becomes: `user`
111    /// - Second key "name" becomes: `user[name]`
112    /// - Third key "first" becomes: `user[name][first]`
113    fn push_key(&mut self, newkey: &[u8]) -> Result<()> {
114        if self.key.len() > self.config.max_depth {
115            return Err(Error::MaxSerializationDepthExceeded(self.config.max_depth));
116        }
117        let first_key_segment = self.key.is_empty();
118
119        // estimate the required capacity based on
120        // the key length and encoding
121        // note that if we do require percent-encoding
122        // the key, then we'll probably need to grow
123        // the capacity -- we're being optimistic here
124        // that the common case does not need to encode
125        let estimated_capacity = newkey.len()
126            + if first_key_segment { 0 } else { 2 }
127            + if self.config.use_form_encoding { 6 } else { 2 };
128        let mut segment = Vec::with_capacity(estimated_capacity);
129        if !first_key_segment {
130            if self.config.use_form_encoding {
131                segment.extend_from_slice(b"%5B");
132            } else {
133                segment.push(b'[');
134            }
135        }
136
137        if newkey
138            .iter()
139            .all(|b| b.is_ascii_alphanumeric() || *b == b'-' || *b == b'_' || *b == b'.')
140        {
141            // optimization for the case where the key
142            // is alphanumeric or a few special characters
143            // this avoids the percent-encoding overhead
144            segment.extend_from_slice(newkey);
145        } else {
146            for encoded in encode(newkey, self.config.use_form_encoding) {
147                segment.extend_from_slice(&encoded);
148            }
149        }
150
151        if !first_key_segment {
152            if self.config.use_form_encoding {
153                segment.extend_from_slice(b"%5D");
154            } else {
155                segment.push(b']');
156            }
157        }
158        self.key.push(segment);
159        Ok(())
160    }
161
162    fn write_key_stack(&mut self) -> Result<()> {
163        if self.key.is_empty() {
164            // this is the case when we used `write_key_out`
165            // to write the key without pushing it to the stack
166            return Ok(());
167        }
168        if self.first_kv {
169            self.first_kv = false;
170        } else {
171            self.writer.write_all(b"&")?;
172        }
173        let Some(first_segment) = self.key.first() else {
174            return Err(Error::Custom("internal error: no key found".to_string()));
175        };
176
177        // write the key segments
178        self.writer.write_all(first_segment)?;
179        for segment in self.key.iter().skip(1) {
180            self.writer.write_all(segment)?;
181        }
182
183        Ok(())
184    }
185
186    fn pop_key(&mut self) -> Result<()> {
187        let popped = self.key.pop();
188        if popped.is_none() {
189            return Err(Error::Custom("internal error: no key found".to_string()));
190        }
191        Ok(())
192    }
193
194    fn write_value(&mut self, value: &[u8]) -> Result<()> {
195        self.write_key_stack()?;
196        self.writer.write_all(b"=")?;
197        for encoded in encode(value, self.config.use_form_encoding) {
198            self.writer.write_all(&encoded)?;
199        }
200        Ok(())
201    }
202
203    fn write_unit(&mut self) -> Result<()> {
204        self.write_key_stack()?;
205        self.writer.write_all(b"=")?;
206        Ok(())
207    }
208
209    fn write_no_value(&mut self) -> Result<()> {
210        self.write_key_stack()?;
211        Ok(())
212    }
213}
214
215macro_rules! serialize_itoa {
216    (
217        $($ty:ty => $meth:ident,)*) => {
218        $(
219            #[allow(unused_mut)]
220            fn $meth(mut self, v: $ty) -> Result<Self::Ok> {
221                let mut buffer = itoa::Buffer::new();
222                let key = buffer.format(v);
223                self.write_value(key.as_bytes())?;
224                Ok(())
225            }
226        )*
227    };
228}
229
230macro_rules! serialize_ryu {
231    (
232        $($ty:ty => $meth:ident,)*) => {
233        $(
234            #[allow(unused_mut)]
235            fn $meth(mut self, v: $ty) -> Result<Self::Ok> {
236                let mut buffer = ryu::Buffer::new();
237                let key = buffer.format(v);
238                self.write_value(key.as_bytes())?;
239                Ok(())
240            }
241        )*
242    };
243}
244
245impl<'a, W: Write> ser::Serializer for &'a mut QsSerializer<W> {
246    type Ok = ();
247    type Error = Error;
248    type SerializeSeq = QsSeq<'a, W>;
249    type SerializeTuple = QsSeq<'a, W>;
250    type SerializeTupleStruct = QsSeq<'a, W>;
251    type SerializeTupleVariant = QsSeq<'a, W>;
252    type SerializeMap = QsMap<'a, W>;
253    type SerializeStruct = Self;
254    type SerializeStructVariant = Self;
255
256    serialize_itoa! {
257        u8  => serialize_u8,
258        u16 => serialize_u16,
259        u32 => serialize_u32,
260        u64 => serialize_u64,
261        i8  => serialize_i8,
262        i16 => serialize_i16,
263        i32 => serialize_i32,
264        i64 => serialize_i64,
265    }
266    serialize_ryu! {
267        f32 => serialize_f32,
268        f64 => serialize_f64,
269    }
270
271    fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok> {
272        self.write_value(value)
273    }
274
275    fn serialize_unit(self) -> Result<Self::Ok> {
276        self.write_unit()
277    }
278
279    fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok> {
280        self.write_unit()
281    }
282
283    fn serialize_unit_variant(
284        self,
285        _name: &'static str,
286        _variant_index: u32,
287        variant: &'static str,
288    ) -> Result<Self::Ok> {
289        self.write_value(variant.as_bytes())?;
290        Ok(())
291    }
292
293    fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
294        self,
295        _name: &'static str,
296        value: &T,
297    ) -> Result<Self::Ok> {
298        value.serialize(self)
299    }
300
301    fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
302        self,
303        _name: &'static str,
304        _variant_index: u32,
305        variant: &'static str,
306        value: &T,
307    ) -> Result<Self::Ok> {
308        self.push_key(variant.as_bytes())?;
309        value.serialize(&mut *self)?;
310        self.pop_key()
311    }
312
313    fn serialize_none(self) -> Result<Self::Ok> {
314        self.write_no_value()?;
315        Ok(())
316    }
317
318    fn serialize_some<T: ?Sized + ser::Serialize>(self, value: &T) -> Result<Self::Ok> {
319        value.serialize(&mut *self)?;
320        Ok(())
321    }
322
323    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
324        Ok(QsSeq::new(self))
325    }
326
327    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
328        Ok(QsSeq::new(self))
329    }
330
331    fn serialize_tuple_struct(
332        self,
333        _name: &'static str,
334        _len: usize,
335    ) -> Result<Self::SerializeTupleStruct> {
336        Ok(QsSeq::new(self))
337    }
338
339    fn serialize_tuple_variant(
340        self,
341        _name: &'static str,
342        _variant_index: u32,
343        variant: &'static str,
344        _len: usize,
345    ) -> Result<Self::SerializeTupleVariant> {
346        self.push_key(variant.as_bytes())?;
347        Ok(QsSeq::new(self))
348    }
349
350    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
351        Ok(QsMap::new(self))
352    }
353
354    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
355        Ok(self)
356    }
357
358    fn serialize_struct_variant(
359        self,
360        _name: &'static str,
361        _variant_index: u32,
362        variant: &'static str,
363        _len: usize,
364    ) -> Result<Self::SerializeStructVariant> {
365        self.push_key(variant.as_bytes())?;
366        Ok(self)
367    }
368
369    fn serialize_bool(self, v: bool) -> std::result::Result<Self::Ok, Self::Error> {
370        let key = if v {
371            b"true" as &'static [u8]
372        } else {
373            b"false"
374        };
375        self.write_value(key)?;
376        Ok(())
377    }
378
379    fn serialize_char(self, v: char) -> std::result::Result<Self::Ok, Self::Error> {
380        let mut b = [0; 4];
381        let key = v.encode_utf8(&mut b);
382        self.write_value(key.as_bytes())?;
383        Ok(())
384    }
385
386    fn serialize_str(self, v: &str) -> std::result::Result<Self::Ok, Self::Error> {
387        self.write_value(v.as_bytes())?;
388        Ok(())
389    }
390}
391
392impl ser::Error for Error {
393    fn custom<T>(msg: T) -> Self
394    where
395        T: Display,
396    {
397        Error::Custom(msg.to_string())
398    }
399}
400
401#[doc(hidden)]
402pub struct QsSeq<'s, W: Write> {
403    qs: &'s mut QsSerializer<W>,
404    counter: usize,
405}
406
407impl<'a, W: Write> QsSeq<'a, W> {
408    fn new(qs: &'a mut QsSerializer<W>) -> Self {
409        Self { qs, counter: 0 }
410    }
411
412    /// Pushes the key to the serializer.
413    fn push_key(&mut self) -> Result<()> {
414        match self.qs.config.array_format {
415            crate::ArrayFormat::Indexed => {
416                // indexed arrays have keys like `[0]`, `[1]`, etc.
417                let mut buffer = itoa::Buffer::new();
418                // encode the next integer key
419                let key = buffer.format(self.counter);
420                self.qs.push_key(key.as_bytes())?;
421            }
422            crate::ArrayFormat::EmptyIndexed => {
423                // empty indexed arrays have keys like `[]`
424                self.qs.push_key(b"")?;
425            }
426            crate::ArrayFormat::Unindexed => {
427                // unindexed arrays have no keys, so nothing to push
428            }
429        }
430
431        // increment the key
432        self.counter += 1;
433        Ok(())
434    }
435
436    fn pop_key(&mut self) -> Result<()> {
437        // pop the key from the serializer (if we pushed one)
438        if matches!(
439            self.qs.config.array_format,
440            crate::ArrayFormat::Indexed | crate::ArrayFormat::EmptyIndexed
441        ) {
442            self.qs.pop_key()?;
443        }
444        Ok(())
445    }
446}
447
448impl<W: Write> ser::SerializeTuple for QsSeq<'_, W> {
449    type Ok = ();
450    type Error = Error;
451    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
452    where
453        T: ser::Serialize + ?Sized,
454    {
455        self.push_key()?;
456        value.serialize(&mut *self.qs)?;
457        self.pop_key()
458    }
459
460    fn end(self) -> Result<Self::Ok> {
461        // if we didn't serialize any elements, we'll write a null
462        // value
463        if self.counter == 0 {
464            self.qs.write_unit()?;
465        }
466        Ok(())
467    }
468}
469
470impl<W: Write> ser::SerializeSeq for QsSeq<'_, W> {
471    type Ok = ();
472    type Error = Error;
473    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
474    where
475        T: ser::Serialize + ?Sized,
476    {
477        self.push_key()?;
478        value.serialize(&mut *self.qs)?;
479        self.pop_key()
480    }
481    fn end(self) -> Result<Self::Ok> {
482        // if we didn't serialize any elements, we'll write a null
483        // value
484        if self.counter == 0 {
485            self.qs.write_unit()?;
486        }
487        Ok(())
488    }
489}
490
491impl<W: Write> ser::SerializeTupleVariant for QsSeq<'_, W> {
492    type Ok = ();
493    type Error = Error;
494
495    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
496    where
497        T: ser::Serialize + ?Sized,
498    {
499        self.push_key()?;
500        value.serialize(&mut *self.qs)?;
501        self.pop_key()
502    }
503
504    fn end(self) -> Result<Self::Ok> {
505        // after serializing a tuple variant, we need to pop the
506        // variant key
507        self.qs.pop_key()?;
508        Ok(())
509    }
510}
511
512impl<W: Write> ser::SerializeTupleStruct for QsSeq<'_, W> {
513    type Ok = ();
514    type Error = Error;
515
516    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
517    where
518        T: ser::Serialize + ?Sized,
519    {
520        self.push_key()?;
521        value.serialize(&mut *self.qs)?;
522        self.pop_key()
523    }
524
525    fn end(self) -> Result<Self::Ok> {
526        // if we didn't serialize any elements, we'll write a null
527        // value
528        if self.counter == 0 {
529            self.qs.write_unit()?;
530        }
531        Ok(())
532    }
533}
534
535impl<W: Write> ser::SerializeStruct for &mut QsSerializer<W> {
536    type Ok = ();
537    type Error = Error;
538    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
539    where
540        T: ser::Serialize + ?Sized,
541    {
542        self.push_key(key.as_bytes())?;
543        value.serialize(&mut **self)?;
544        self.pop_key()
545    }
546    fn end(self) -> Result<Self::Ok> {
547        Ok(())
548    }
549}
550
551impl<W: Write> ser::SerializeStructVariant for &mut QsSerializer<W> {
552    type Ok = ();
553    type Error = Error;
554
555    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
556    where
557        T: ser::Serialize + ?Sized,
558    {
559        self.push_key(key.as_bytes())?;
560        value.serialize(&mut **self)?;
561        self.pop_key()
562    }
563
564    fn end(self) -> Result<Self::Ok> {
565        self.pop_key()?;
566        Ok(())
567    }
568}
569
570#[doc(hidden)]
571pub struct QsMap<'s, W: Write> {
572    qs: &'s mut QsSerializer<W>,
573    empty: bool,
574}
575
576impl<'a, W: Write> QsMap<'a, W> {
577    fn new(qs: &'a mut QsSerializer<W>) -> Self {
578        Self { qs, empty: true }
579    }
580}
581
582impl<W: Write> ser::SerializeMap for QsMap<'_, W> {
583    type Ok = ();
584    type Error = Error;
585
586    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
587    where
588        T: ser::Serialize + ?Sized,
589    {
590        self.empty = false;
591        key.serialize(KeySerializer::new(self.qs))?;
592        Ok(())
593    }
594
595    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
596    where
597        T: ser::Serialize + ?Sized,
598    {
599        value.serialize(&mut *self.qs)?;
600        self.qs.pop_key()
601    }
602
603    fn end(self) -> Result<Self::Ok> {
604        if self.empty {
605            // if we didn't serialize any elements, we'll write a null
606            // value
607            self.qs.write_unit()?;
608        }
609        Ok(())
610    }
611}
612
613macro_rules! serialize_key_itoa {
614    (
615        $($ty:ty => $meth:ident,)*) => {
616        $(
617            #[allow(unused_mut)]
618            fn $meth(mut self, v: $ty) -> Result<Self::Ok> {
619                let mut buffer = itoa::Buffer::new();
620                let key = buffer.format(v);
621                self.push_key(key.as_bytes())?;
622                Ok(())
623            }
624        )*
625    };
626}
627
628macro_rules! serialize_key_ryu {
629    (
630        $($ty:ty => $meth:ident,)*) => {
631        $(
632            #[allow(unused_mut)]
633            fn $meth(mut self, v: $ty) -> Result<Self::Ok> {
634                let mut buffer = ryu::Buffer::new();
635                let key = buffer.format(v);
636                self.push_key(key.as_bytes())?;
637                Ok(())
638            }
639        )*
640    };
641}
642
643struct KeySerializer<'a, W: Write> {
644    qs: &'a mut QsSerializer<W>,
645}
646
647impl<'a, W: Write> KeySerializer<'a, W> {
648    fn new(qs: &'a mut QsSerializer<W>) -> Self {
649        Self { qs }
650    }
651
652    fn push_key(&mut self, key: &[u8]) -> Result<()> {
653        self.qs.push_key(key)?;
654        Ok(())
655    }
656}
657
658impl<W: Write> ser::Serializer for KeySerializer<'_, W> {
659    type Ok = ();
660    type Error = Error;
661    type SerializeSeq = ser::Impossible<Self::Ok, Error>;
662    type SerializeTuple = ser::Impossible<Self::Ok, Error>;
663    type SerializeTupleStruct = ser::Impossible<Self::Ok, Error>;
664    type SerializeTupleVariant = ser::Impossible<Self::Ok, Error>;
665    type SerializeMap = ser::Impossible<Self::Ok, Error>;
666    type SerializeStruct = ser::Impossible<Self::Ok, Error>;
667    type SerializeStructVariant = ser::Impossible<Self::Ok, Error>;
668
669    serialize_key_itoa! {
670        u8  => serialize_u8,
671        u16 => serialize_u16,
672        u32 => serialize_u32,
673        u64 => serialize_u64,
674        i8  => serialize_i8,
675        i16 => serialize_i16,
676        i32 => serialize_i32,
677        i64 => serialize_i64,
678    }
679    serialize_key_ryu! {
680        f32 => serialize_f32,
681        f64 => serialize_f64,
682    }
683
684    fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok> {
685        self.qs.push_key(value)?;
686        Ok(())
687    }
688
689    /// Returns an error.
690    fn serialize_unit(self) -> Result<Self::Ok> {
691        Err(Error::Unsupported)
692    }
693
694    /// Returns an error.
695    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
696        Err(Error::Unsupported)
697    }
698
699    fn serialize_unit_variant(
700        self,
701        _name: &'static str,
702        _variant_index: u32,
703        variant: &'static str,
704    ) -> Result<Self::Ok> {
705        self.qs.push_key(variant.as_bytes())?;
706        Ok(())
707    }
708
709    /// Returns an error.
710    fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
711        self,
712        _name: &'static str,
713        _value: &T,
714    ) -> Result<Self::Ok> {
715        Err(Error::Unsupported)
716    }
717
718    /// Returns an error.
719    fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
720        self,
721        _name: &'static str,
722        _variant_index: u32,
723        _variant: &'static str,
724        _value: &T,
725    ) -> Result<Self::Ok> {
726        Err(Error::Unsupported)
727    }
728
729    /// Returns an error.
730    fn serialize_none(self) -> Result<Self::Ok> {
731        Err(Error::Unsupported)
732    }
733
734    /// Returns an error.
735    fn serialize_some<T: ?Sized + ser::Serialize>(self, _value: &T) -> Result<Self::Ok> {
736        Err(Error::Unsupported)
737    }
738
739    /// Returns an error.
740    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
741        Err(Error::Unsupported)
742    }
743
744    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
745        Err(Error::Unsupported)
746    }
747
748    /// Returns an error.
749    fn serialize_tuple_struct(
750        self,
751        _name: &'static str,
752        _len: usize,
753    ) -> Result<Self::SerializeTupleStruct> {
754        Err(Error::Unsupported)
755    }
756
757    fn serialize_tuple_variant(
758        self,
759        _name: &'static str,
760        _variant_index: u32,
761        _variant: &'static str,
762        _len: usize,
763    ) -> Result<Self::SerializeTupleVariant> {
764        Err(Error::Unsupported)
765    }
766
767    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
768        Err(Error::Unsupported)
769    }
770
771    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
772        Err(Error::Unsupported)
773    }
774
775    fn serialize_struct_variant(
776        self,
777        _name: &'static str,
778        _variant_index: u32,
779        _variant: &'static str,
780        _len: usize,
781    ) -> Result<Self::SerializeStructVariant> {
782        Err(Error::Unsupported)
783    }
784
785    fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
786        let key = if v {
787            b"true" as &'static [u8]
788        } else {
789            b"false"
790        };
791        self.qs.push_key(key)?;
792        Ok(())
793    }
794
795    fn serialize_char(self, v: char) -> std::result::Result<Self::Ok, Self::Error> {
796        let mut b = [0; 4];
797        let key = v.encode_utf8(&mut b);
798        self.qs.push_key(key.as_bytes())?;
799        Ok(())
800    }
801
802    fn serialize_str(self, v: &str) -> std::result::Result<Self::Ok, Self::Error> {
803        self.qs.push_key(v.as_bytes())?;
804        Ok(())
805    }
806}