Skip to main content

deser_urlencoded/
ser.rs

1use std::borrow::Cow;
2
3use deser_core::ext::Number;
4use deser_core::ser::SerializeRef;
5use deser_core::ser::{self, EventSink, SerializeDriver};
6use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Serialize, State};
7
8use crate::Nesting;
9use crate::encoding::encode;
10
11/// How sequences are written.
12///
13/// ```
14/// use std::collections::BTreeMap;
15/// use deser_urlencoded::{ArrayFormat, SerializerConfig};
16///
17/// let value = BTreeMap::from([("a", vec![1, 2])]);
18/// let with = |arrays| {
19///     SerializerConfig::builder().arrays(arrays).build().to_string(&value).unwrap()
20/// };
21/// assert_eq!(with(ArrayFormat::Repeat), "a=1&a=2");
22/// assert_eq!(with(ArrayFormat::Brackets), "a%5B%5D=1&a%5B%5D=2");
23/// assert_eq!(with(ArrayFormat::Indices), "a%5B0%5D=1&a%5B1%5D=2");
24/// ```
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
26#[non_exhaustive]
27pub enum ArrayFormat {
28    /// The key is repeated for every element (`a=1&a=2`).
29    ///
30    /// This is what HTML forms send for `<select multiple>` and what
31    /// `URLSearchParams` produces.  The elements have to be atoms.
32    #[default]
33    Repeat,
34    /// The key is repeated with empty brackets (`a[]=1&a[]=2`).
35    ///
36    /// The elements have to be atoms.
37    Brackets,
38    /// The key is repeated with the index of the element (`a[0]=1&a[1]=2`,
39    /// with [`Nesting::Dots`] `a.0=1&a.1=2`).
40    ///
41    /// This is the only format that supports sequences of maps and
42    /// sequences.
43    Indices,
44}
45
46/// Configures how values are serialized to query strings.
47///
48/// The value has to serialize to a map (for instance a struct or a map
49/// type), or to a sequence of key-value pairs (like `Vec<(&str, &str)>`).
50/// Null values (like `None`) of map entries are skipped, null values in
51/// sequences are written as empty values.  Maps and sequences that are
52/// empty are not written as query strings cannot represent them.
53///
54/// Keys and values are percent-encoded like `application/x-www-form-urlencoded`
55/// (ASCII alphanumerics and `*-._` are kept, space is written as `+`).
56/// Numbers are written with the shortest text that reads back as the same
57/// value, booleans as `true` and `false` and bytes as base64 (or the
58/// [`BytesFormat`](deser_core::BytesFormat) of the context).
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct SerializerConfig {
61    arrays: ArrayFormat,
62    nesting: Nesting,
63    space_as_plus: bool,
64    context: deser_core::Context,
65}
66
67impl Default for SerializerConfig {
68    fn default() -> SerializerConfig {
69        SerializerConfig::new()
70    }
71}
72
73impl SerializerConfig {
74    /// Creates the default configuration.
75    pub const fn new() -> SerializerConfig {
76        SerializerConfig {
77            arrays: ArrayFormat::Repeat,
78            nesting: Nesting::Brackets,
79            space_as_plus: true,
80            context: deser_core::Context::new(),
81        }
82    }
83
84    /// Returns a builder for the configuration (see [`SerializerConfigBuilder`]).
85    pub const fn builder() -> SerializerConfigBuilder {
86        SerializerConfigBuilder::new()
87    }
88
89    /// Returns a builder that starts with this configuration.
90    pub const fn into_builder(self) -> SerializerConfigBuilder {
91        SerializerConfigBuilder { value: self }
92    }
93
94    /// Sets the context the values are serialized in.
95    ///
96    /// The values of the context are the defaults of the extension values
97    /// of the state (see [`Context`](deser_core::Context)), for instance
98    /// the [`BytesFormat`](deser_core::BytesFormat).  The serializers and
99    /// writers created with the configuration use this context.  A context set on
100    /// the driver takes precedence.
101    pub fn set_context(&mut self, context: deser_core::Context) {
102        self.context = context;
103    }
104
105    /// Returns the context the values are serialized in.
106    pub fn context(&self) -> &deser_core::Context {
107        &self.context
108    }
109
110    /// Gives the context to a driver which has none.
111    #[inline]
112    fn apply_context(&self, driver: &mut SerializeDriver<'_>) {
113        if !self.context.is_empty() {
114            driver.set_default_context(self.context.clone());
115        }
116    }
117
118    /// Sets how sequences are written.
119    ///
120    /// The default is [`ArrayFormat::Repeat`].
121    pub const fn set_arrays(&mut self, format: ArrayFormat) {
122        self.arrays = format;
123    }
124
125    /// Sets how the keys of nested maps are written.
126    ///
127    /// The default is [`Nesting::Brackets`] (`a[b]=1`), with
128    /// [`Nesting::Dots`] they are written as `a.b=1`.  With
129    /// [`Nesting::Flat`] nested maps are an error.
130    pub const fn set_nesting(&mut self, nesting: Nesting) {
131        self.nesting = nesting;
132    }
133
134    /// Sets if spaces are written as `+` (the default) or as `%20`.
135    pub const fn set_space_as_plus(&mut self, yes: bool) {
136        self.space_as_plus = yes;
137    }
138
139    /// Serializes the given value.
140    pub fn to_string<T: Serialize + ?Sized>(&self, value: &T) -> Result<String, Error> {
141        self.to_string_ref(SerializeRef::new(&value))
142    }
143
144    /// Serializes the given value with a configured driver.
145    ///
146    /// The callback is invoked with the driver before the serialization
147    /// starts, for instance to add [`Layer`](deser_core::ser::Layer)s.
148    pub fn to_string_with<F, T: Serialize + ?Sized>(
149        &self,
150        value: &T,
151        setup: F,
152    ) -> Result<String, Error>
153    where
154        F: FnOnce(&mut SerializeDriver<'_>),
155    {
156        let mut driver = SerializeDriver::new(&value);
157        setup(&mut driver);
158        self.apply_context(&mut driver);
159        let mut out = String::new();
160        self.serialize_driver(&mut driver, &mut out)?;
161        Ok(out)
162    }
163
164    /// Serializes a value whose type is erased (see
165    /// [`to_string`](Self::to_string)).
166    ///
167    /// This is not generic: the code that exists for every type only
168    /// erases it.
169    fn to_string_ref(&self, value: SerializeRef<'_>) -> Result<String, Error> {
170        let mut driver = SerializeDriver::from_ref(value);
171        self.apply_context(&mut driver);
172        let mut out = String::new();
173        self.serialize_driver(&mut driver, &mut out)?;
174        Ok(out)
175    }
176
177    /// Creates the writer of a value which writes into the output.
178    pub(crate) fn value_writer(&self, out: String, bytes: BytesFormat) -> Writer {
179        Writer {
180            config: self.clone(),
181            bytes,
182            separate: false,
183            out,
184            key: String::new(),
185            stack: Vec::new(),
186            limit: usize::MAX,
187        }
188    }
189
190    /// Serializes (a part of) the value of a driver and appends it to the
191    /// output.
192    ///
193    /// The progress of the value is kept in `value` (see
194    /// `StreamSerializer::drive_partial`), `true` is returned once the
195    /// value is complete.  `separate` is `true` if parameters were written
196    /// before (the parameters of more than one value are joined).  If this
197    /// fails, what was appended by the call is removed from the output.
198    pub(crate) fn serialize_part(
199        &self,
200        value: &mut Option<Box<Writer>>,
201        driver: &mut SerializeDriver<'_>,
202        out: &mut String,
203        separate: &mut bool,
204        limit: usize,
205    ) -> Result<bool, Error> {
206        // a value that is written at once is written into the output
207        // directly without boxing the writer
208        if value.is_none() && limit == usize::MAX {
209            return self.serialize_whole(driver, out, separate).map(|()| true);
210        }
211        let len = out.len();
212        let mut writer = value.take().unwrap_or_else(|| {
213            let mut writer = self.value_writer(String::new(), BytesFormat::of(driver.state()));
214            writer.separate = *separate;
215            Box::new(writer)
216        });
217        // the writer writes into an empty output directly, otherwise its
218        // output is appended
219        let adopt = out.is_empty();
220        if adopt {
221            writer.out = std::mem::take(out);
222        }
223        // after an error the value is abandoned, its writer is dropped
224        writer.limit = limit;
225        let rv = driver.drive_until(&mut *writer);
226        let output = std::mem::take(&mut writer.out);
227        let done = match rv {
228            Ok(done) => done,
229            Err(err) => {
230                if adopt {
231                    *out = output;
232                }
233                out.truncate(len);
234                return Err(err);
235            }
236        };
237        if adopt {
238            *out = output;
239        } else {
240            out.push_str(&output);
241        }
242        if done {
243            *separate = writer.separate;
244        } else {
245            *value = Some(writer);
246        }
247        Ok(done)
248    }
249
250    /// Serializes the value of a driver at once and appends it to the
251    /// output.
252    ///
253    /// Unlike `serialize_part` this does not refer to the pausable instance
254    /// of the driver which is only needed by stream serializers.  If this
255    /// fails, what was appended by the call is removed from the output.
256    fn serialize_whole(
257        &self,
258        driver: &mut SerializeDriver<'_>,
259        out: &mut String,
260        separate: &mut bool,
261    ) -> Result<(), Error> {
262        let len = out.len();
263        let mut writer = self.value_writer(std::mem::take(out), BytesFormat::of(driver.state()));
264        writer.separate = *separate;
265        let rv = driver.drive(|event, state| writer.event(event, state));
266        *out = writer.out;
267        if let Err(err) = rv {
268            out.truncate(len);
269            return Err(err);
270        }
271        *separate = writer.separate;
272        Ok(())
273    }
274
275    /// Serializes the value of a driver and appends it to the output.
276    pub(crate) fn serialize_driver(
277        &self,
278        driver: &mut SerializeDriver<'_>,
279        out: &mut String,
280    ) -> Result<(), Error> {
281        self.serialize_whole(driver, out, &mut false)
282    }
283}
284
285/// Builds a [`SerializerConfig`].
286///
287/// The methods have the names of the setters of [`SerializerConfig`] (without `set_`).
288#[derive(Debug, Clone)]
289#[must_use]
290pub struct SerializerConfigBuilder {
291    value: SerializerConfig,
292}
293
294impl SerializerConfigBuilder {
295    /// Creates a builder that starts with the default.
296    pub const fn new() -> SerializerConfigBuilder {
297        SerializerConfigBuilder {
298            value: SerializerConfig::new(),
299        }
300    }
301
302    /// Sets how sequences are written.
303    ///
304    /// See [`SerializerConfig::set_arrays`].
305    pub const fn arrays(mut self, format: ArrayFormat) -> SerializerConfigBuilder {
306        self.value.set_arrays(format);
307        self
308    }
309
310    /// Sets how the keys of nested maps are written.
311    ///
312    /// See [`SerializerConfig::set_nesting`].
313    pub const fn nesting(mut self, nesting: Nesting) -> SerializerConfigBuilder {
314        self.value.set_nesting(nesting);
315        self
316    }
317
318    /// Sets if spaces are written as `+` (the default) or as `%20`.
319    ///
320    /// See [`SerializerConfig::set_space_as_plus`].
321    pub const fn space_as_plus(mut self, yes: bool) -> SerializerConfigBuilder {
322        self.value.set_space_as_plus(yes);
323        self
324    }
325
326    /// Sets the context the values are serialized in.
327    ///
328    /// See [`SerializerConfig::set_context`].
329    pub fn context(mut self, context: deser_core::Context) -> SerializerConfigBuilder {
330        self.value.set_context(context);
331        self
332    }
333
334    /// Returns the built [`SerializerConfig`].
335    pub const fn build(self) -> SerializerConfig {
336        // the value cannot be moved out of the builder in a const fn as the
337        // builder needs dropping (the context has a destructor)
338        // SAFETY: the value is read once and the builder is forgotten
339        let value = unsafe { core::ptr::read(&self.value) };
340        core::mem::forget(self);
341        value
342    }
343}
344
345impl Default for SerializerConfigBuilder {
346    fn default() -> SerializerConfigBuilder {
347        SerializerConfigBuilder::new()
348    }
349}
350
351/// Serializes values into query strings.
352///
353/// More than one value can be serialized, their parameters are joined.
354///
355/// ```
356/// use std::collections::BTreeMap;
357/// use deser_urlencoded::Serializer;
358///
359/// let mut serializer = Serializer::new();
360/// serializer.serialize(&BTreeMap::from([("a", 1)])).unwrap();
361/// serializer.serialize(&BTreeMap::from([("b", 2)])).unwrap();
362/// assert_eq!(serializer.finish(), "a=1&b=2");
363/// ```
364///
365/// The serializer is also the stream serializer of query strings (see
366/// [`StreamSerializer`](ser::StreamSerializer)): the output can be taken
367/// while values are written, and large values can be written in parts.
368/// To write to a [`Write`](std::io::Write) use
369/// [`SerializerConfig::to_writer`] or a
370/// [`deser::io::Writer`](https://docs.rs/deser/latest/deser/io/struct.Writer.html).
371pub struct Serializer {
372    config: SerializerConfig,
373    out: String,
374    // parameters were written, the next ones are separated with `&`
375    separate: bool,
376    // the value that is written in parts
377    value: Option<Box<Writer>>,
378    // a value was started with `drive_partial` and is not complete
379    in_progress: bool,
380}
381
382impl Default for Serializer {
383    fn default() -> Serializer {
384        Serializer::new()
385    }
386}
387
388impl Clone for Serializer {
389    /// Clones the serializer.
390    ///
391    /// The clone of a serializer that writes a value in parts cannot write
392    /// more values (see
393    /// [`StreamSerializer::in_progress`](ser::StreamSerializer::in_progress)).
394    fn clone(&self) -> Serializer {
395        Serializer {
396            config: self.config.clone(),
397            out: self.out.clone(),
398            separate: self.separate,
399            value: None,
400            in_progress: self.in_progress,
401        }
402    }
403}
404
405impl std::fmt::Debug for Serializer {
406    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
407        f.debug_struct("Serializer")
408            .field("config", &self.config)
409            .field("output", &self.out)
410            .field("in_progress", &self.in_progress)
411            .finish()
412    }
413}
414
415impl Serializer {
416    /// Creates a serializer.
417    pub fn new() -> Serializer {
418        Serializer::with_config(SerializerConfig::new())
419    }
420
421    /// Creates a serializer with the given configuration.
422    pub fn with_config(config: SerializerConfig) -> Serializer {
423        Serializer {
424            config,
425            out: String::new(),
426            separate: false,
427            value: None,
428            in_progress: false,
429        }
430    }
431
432    /// Returns the configuration.
433    pub fn config(&self) -> &SerializerConfig {
434        &self.config
435    }
436
437    /// Serializes a value.
438    ///
439    /// If the value fails to serialize, nothing is written.
440    pub fn serialize<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
441        ser::Serializer::serialize(self, value)
442    }
443
444    /// Serializes a value with a configured driver.
445    ///
446    /// The callback is invoked with the driver before the value is
447    /// serialized, for instance to add [`Layer`](deser_core::ser::Layer)s.
448    pub fn serialize_with<F, T: Serialize + ?Sized>(
449        &mut self,
450        value: &T,
451        setup: F,
452    ) -> Result<(), Error>
453    where
454        F: FnOnce(&mut SerializeDriver<'_>),
455    {
456        ser::Serializer::serialize_with(self, value, setup)
457    }
458
459    /// Returns the output written so far (that was not cleared).
460    pub fn as_str(&self) -> &str {
461        &self.out
462    }
463
464    /// Returns the output.
465    pub fn finish(self) -> String {
466        self.out
467    }
468}
469
470impl ser::Serializer for Serializer {
471    fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
472        // only `drive_partial` continues a value
473        if self.in_progress {
474            return Err(Error::in_progress());
475        }
476        ser::StreamSerializer::drive_partial(self, driver, usize::MAX).map(|_| ())
477    }
478}
479
480impl ser::StreamSerializer for Serializer {
481    fn output(&self) -> &[u8] {
482        self.out.as_bytes()
483    }
484
485    fn clear_output(&mut self) {
486        self.out.clear();
487    }
488
489    fn supports_partial(&self) -> bool {
490        true
491    }
492
493    fn drive_partial(
494        &mut self,
495        driver: &mut SerializeDriver<'_>,
496        limit: usize,
497    ) -> Result<bool, Error> {
498        if !self.config.context.is_empty() {
499            driver.set_default_context(self.config.context.clone());
500        }
501        if self.value.is_none() && self.in_progress {
502            return Err(Error::in_progress());
503        }
504        // the parts of a value that failed stay written (see
505        // `in_progress`)
506        if !self.config.serialize_part(
507            &mut self.value,
508            driver,
509            &mut self.out,
510            &mut self.separate,
511            limit,
512        )? {
513            self.in_progress = true;
514            return Ok(false);
515        }
516        self.in_progress = false;
517        Ok(true)
518    }
519
520    fn in_progress(&self) -> bool {
521        self.in_progress
522    }
523}
524
525#[cfg(feature = "io")]
526impl SerializerConfig {
527    /// Creates a writer of form data (see
528    /// [`deser::io::Writer`](deser_core::io::Writer)).
529    ///
530    /// The parameters of more than one value are joined.  The output of
531    /// large values is written in parts while they are serialized.
532    pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
533        deser_core::io::Writer::new(writer, Serializer::with_config(self.clone()))
534    }
535
536    /// Serializes a value as form data to a writer.
537    ///
538    /// See [`to_writer`].
539    pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
540        &self,
541        writer: W,
542        value: &T,
543    ) -> Result<(), Error> {
544        self.writer(writer).write(value)
545    }
546}
547
548/// Serializes a value as form data to a writer.
549///
550/// ```
551/// use std::collections::BTreeMap;
552///
553/// let mut out = Vec::new();
554/// deser_urlencoded::to_writer(&mut out, &BTreeMap::from([("a", 1)]))
555///     .unwrap();
556/// assert_eq!(out, b"a=1");
557/// ```
558#[cfg(feature = "io")]
559pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
560    writer: W,
561    value: &T,
562) -> Result<(), Error> {
563    SerializerConfig::new().to_writer(writer, value)
564}
565
566/// Serializes a value to a query string.
567///
568/// This uses the default [`SerializerConfig`], see there for more
569/// information.
570///
571/// ```
572/// #[derive(deser::Serialize)]
573/// struct Params {
574///     cursor: Option<usize>,
575///     per_page: Option<usize>,
576///     username: String,
577///     filter: Vec<&'static str>,
578/// }
579///
580/// let params = Params {
581///     cursor: Some(42),
582///     per_page: None,
583///     username: "boxdot".into(),
584///     filter: vec!["new", "blocked"],
585/// };
586/// assert_eq!(
587///     deser_urlencoded::to_string(&params).unwrap(),
588///     "cursor=42&username=boxdot&filter=new&filter=blocked"
589/// );
590/// ```
591pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, Error> {
592    SerializerConfig::new().to_string(value)
593}
594
595/// A container that is being written.
596enum Frame {
597    /// A map, with the length of the key of the map.
598    Map { prefix: usize },
599    /// A sequence, with the length of its key and the index of the next
600    /// element.
601    Seq { prefix: usize, index: usize },
602    /// A sequence of key-value pairs at the top level.
603    Pairs,
604    /// A key-value pair: 0 if the key is expected next, 1 for the value, 2
605    /// for the end.
606    Pair(u8),
607}
608
609/// Writes the events of a value.
610pub(crate) struct Writer {
611    config: SerializerConfig,
612    /// How bytes are written (from the state).
613    bytes: BytesFormat,
614    /// `true` if the next parameter needs a separator.
615    separate: bool,
616    out: String,
617    /// The key of the current value (not encoded).
618    key: String,
619    stack: Vec<Frame>,
620    /// The driver is paused once the output is this long.
621    limit: usize,
622}
623
624impl EventSink for Writer {
625    fn event(
626        &mut self,
627        event: Event<'_>,
628        _value: SerializeRef<'_>,
629        state: &mut State,
630    ) -> Result<(), Error> {
631        Writer::event(self, event, state)
632    }
633
634    fn pause(&mut self) -> bool {
635        // the output is only appended to
636        self.out.len() >= self.limit
637    }
638}
639
640impl Writer {
641    fn event(&mut self, event: Event, state: &State) -> Result<(), Error> {
642        match (self.stack.last_mut(), event) {
643            (None, Event::MapStart(_)) => self.stack.push(Frame::Map { prefix: 0 }),
644            (None, Event::SeqStart(_)) => self.stack.push(Frame::Pairs),
645            (None, Event::Atom(Atom::Null)) => {}
646            (None, _) => {
647                return Err(Error::new(
648                    ErrorKind::UnsupportedType,
649                    "query strings hold maps or sequences of key-value pairs",
650                ));
651            }
652
653            (Some(Frame::Map { .. }), Event::MapEnd) => {
654                self.stack.pop();
655            }
656            (Some(&mut Frame::Map { prefix }), event) => {
657                if state.is_map_key() {
658                    let key = match event {
659                        Event::Atom(ref atom) => self.key_text(atom)?,
660                        _ => return Err(unsupported_key()),
661                    };
662                    self.key.truncate(prefix);
663                    if prefix > 0 {
664                        // `a[]` is a sequence and `a.` is not nested
665                        if key.is_empty() {
666                            return Err(Error::new(
667                                ErrorKind::UnsupportedType,
668                                "nested keys of query strings must not be empty",
669                            ));
670                        }
671                        self.push_nested(&key);
672                    } else {
673                        self.key.push_str(&key);
674                    }
675                } else {
676                    self.value(event, false)?;
677                }
678            }
679
680            (Some(Frame::Seq { .. }), Event::SeqEnd) => {
681                self.stack.pop();
682            }
683            (
684                Some(&mut Frame::Seq {
685                    prefix,
686                    ref mut index,
687                }),
688                event,
689            ) => {
690                let element = *index;
691                *index += 1;
692                self.key.truncate(prefix);
693                match self.config.arrays {
694                    ArrayFormat::Repeat => {}
695                    ArrayFormat::Brackets => self.key.push_str("[]"),
696                    ArrayFormat::Indices => self.push_nested(&element.to_string()),
697                }
698                if self.config.arrays != ArrayFormat::Indices
699                    && matches!(event, Event::MapStart(_) | Event::SeqStart(_))
700                {
701                    return Err(Error::new(
702                        ErrorKind::UnsupportedType,
703                        "sequences of maps or sequences require ArrayFormat::Indices",
704                    ));
705                }
706                self.value(event, true)?;
707            }
708
709            (Some(Frame::Pairs), Event::SeqStart(_)) => self.stack.push(Frame::Pair(0)),
710            (Some(Frame::Pairs), Event::SeqEnd) => {
711                self.stack.pop();
712            }
713            (Some(Frame::Pair(state @ 0)), Event::Atom(ref atom)) => {
714                *state = 1;
715                let key = self.key_text(atom)?;
716                self.key.clear();
717                self.key.push_str(&key);
718            }
719            (Some(Frame::Pair(1)), Event::SeqEnd) => {
720                return Err(Error::new(
721                    ErrorKind::UnsupportedType,
722                    "key-value pairs need a value",
723                ));
724            }
725            (Some(Frame::Pair(state @ 1)), event) => {
726                *state = 2;
727                self.value(event, false)?;
728            }
729            (Some(Frame::Pair(2)), Event::SeqEnd) => {
730                self.stack.pop();
731            }
732            (Some(Frame::Pairs | Frame::Pair(_)), _) => {
733                return Err(Error::new(
734                    ErrorKind::UnsupportedType,
735                    "sequences at the top level must hold key-value pairs",
736                ));
737            }
738        }
739        Ok(())
740    }
741
742    /// Writes a value for the current key.
743    fn value(&mut self, event: Event, in_seq: bool) -> Result<(), Error> {
744        match event {
745            Event::Atom(atom) => {
746                let value = match self.value_text(&atom)? {
747                    Some(value) => value,
748                    // nulls in sequences are empty values to keep the
749                    // positions of the other values
750                    None if in_seq => Cow::Borrowed(""),
751                    None => return Ok(()),
752                };
753                self.check_key()?;
754                if self.separate {
755                    self.out.push('&');
756                }
757                self.separate = true;
758                encode(
759                    self.key.as_bytes(),
760                    self.config.space_as_plus,
761                    &mut self.out,
762                );
763                self.out.push('=');
764                encode(value.as_bytes(), self.config.space_as_plus, &mut self.out);
765            }
766            // the nested keys of an empty key (`[a]` or `.a`) are not split
767            // (only repeated empty keys are a sequence)
768            Event::MapStart(_) | Event::SeqStart(_)
769                if self.key.is_empty()
770                    && (matches!(event, Event::MapStart(_))
771                        || self.config.arrays != ArrayFormat::Repeat) =>
772            {
773                return Err(Error::new(
774                    ErrorKind::UnsupportedType,
775                    "maps and sequences in query strings need a key that is not empty",
776                ));
777            }
778            Event::MapStart(_) => {
779                if self.config.nesting == Nesting::Flat {
780                    return Err(Error::new(
781                        ErrorKind::UnsupportedType,
782                        "nested maps are not supported with Nesting::Flat",
783                    ));
784                }
785                self.stack.push(Frame::Map {
786                    prefix: self.key.len(),
787                });
788            }
789            Event::SeqStart(_) => self.stack.push(Frame::Seq {
790                prefix: self.key.len(),
791                index: 0,
792            }),
793            Event::MapEnd | Event::SeqEnd => unreachable!("ends are handled by the frames"),
794        }
795        Ok(())
796    }
797
798    /// Checks that the current key splits into its parts again.
799    ///
800    /// Keys can contain brackets (or dots), which the deserializer would
801    /// take as nested keys (`a[b]` is the key `b` in `a`).  As the
802    /// deserializer decodes keys before it splits them, this cannot be
803    /// escaped.  With [`Nesting::Flat`] keys are taken as they are.
804    fn check_key(&self) -> Result<(), Error> {
805        if self.config.nesting == Nesting::Flat {
806            return Ok(());
807        }
808        // the parts of the key start where the containers start
809        let mut bounds = Vec::new();
810        for frame in &self.stack {
811            match *frame {
812                Frame::Map { prefix } | Frame::Seq { prefix, .. } => bounds.push(prefix),
813                Frame::Pairs | Frame::Pair(_) => bounds.push(0),
814            }
815        }
816        bounds.push(self.key.len());
817        // sequences without indices do not add a part
818        bounds.dedup();
819
820        let mut segments = Vec::new();
821        let first = crate::de::split_key(&self.key, self.config.nesting, &mut segments);
822        let ok = first == bounds.get(1).copied().unwrap_or(self.key.len())
823            && segments.len() + 2 == bounds.len().max(2)
824            && segments
825                .iter()
826                .zip(bounds[1..].windows(2))
827                .all(|(segment, part)| {
828                    let end = match self.config.nesting {
829                        Nesting::Brackets => part[1] - 1,
830                        _ => part[1],
831                    };
832                    match *segment {
833                        crate::de::Segment::Name(start, end2)
834                        | crate::de::Segment::Index(_, start, end2) => {
835                            start == part[0] + 1 && end2 == end
836                        }
837                        crate::de::Segment::Push => &self.key[part[0]..part[1]] == "[]",
838                    }
839                });
840        if ok {
841            Ok(())
842        } else {
843            Err(Error::new(
844                ErrorKind::UnsupportedType,
845                format!(
846                    "the key {:?} would be split differently into nested keys",
847                    self.key
848                ),
849            ))
850        }
851    }
852
853    /// Appends a nested key (or index) to the current key.
854    fn push_nested(&mut self, key: &str) {
855        match self.config.nesting {
856            Nesting::Dots => {
857                self.key.push('.');
858                self.key.push_str(key);
859            }
860            Nesting::Brackets | Nesting::Flat => {
861                self.key.push('[');
862                self.key.push_str(key);
863                self.key.push(']');
864            }
865        }
866    }
867
868    /// Returns the text of a map key.
869    fn key_text<'a>(&self, atom: &'a Atom<'_>) -> Result<Cow<'a, str>, Error> {
870        match atom {
871            Atom::Null | Atom::Bytes(_) => Err(unsupported_key()),
872            atom => self.value_text(atom)?.ok_or_else(unsupported_key),
873        }
874    }
875
876    /// Returns the text of a value, `None` for null.
877    fn value_text<'a>(&self, atom: &'a Atom<'_>) -> Result<Option<Cow<'a, str>>, Error> {
878        Ok(Some(match *atom {
879            Atom::Null => return Ok(None),
880            // values whose type was inferred from text are written as value
881            Atom::Implicit(ref value) => {
882                return Ok(self
883                    .value_text(&value.value().to_atom())?
884                    .map(|text| Cow::Owned(text.into_owned())));
885            }
886            Atom::Bool(value) => Cow::Borrowed(if value { "true" } else { "false" }),
887            Atom::Str(ref value) | Atom::Lexical(ref value) => Cow::Borrowed(&**value),
888            Atom::Char(value) => Cow::Owned(value.to_string()),
889            Atom::U64(value) => Cow::Owned(value.to_string()),
890            Atom::I64(value) => Cow::Owned(value.to_string()),
891            Atom::F32(value) => Cow::Owned(zmij::Buffer::new().format(value).into()),
892            Atom::F64(value) => Cow::Owned(zmij::Buffer::new().format(value).into()),
893            Atom::Bytes(ref bytes) => {
894                let format = bytes.fallback.copied().unwrap_or(self.bytes);
895                Cow::Owned(
896                    format
897                        .encode(bytes)
898                        .or_else(|| BytesFormat::BASE64.encode(bytes))
899                        .unwrap_or_default(),
900                )
901            }
902            Atom::Ext(ref ext) => {
903                if let Some(number) = ext.downcast_value_ref::<Number>() {
904                    // numbers keep their text
905                    Cow::Owned(number.as_str().to_string())
906                } else if let Some(value) = ext.downcast_ref::<u128>() {
907                    Cow::Owned(value.to_string())
908                } else if let Some(value) = ext.downcast_ref::<i128>() {
909                    Cow::Owned(value.to_string())
910                } else {
911                    match ext.fallback() {
912                        Atom::Ext(_) => {
913                            return Err(Error::new(
914                                ErrorKind::UnsupportedType,
915                                format!("query strings do not support {}", ext.name()),
916                            ));
917                        }
918                        fallback => match self.value_text(&fallback)? {
919                            Some(text) => Cow::Owned(text.into_owned()),
920                            None => return Ok(None),
921                        },
922                    }
923                }
924            }
925            _ => {
926                return Err(Error::new(
927                    ErrorKind::UnsupportedType,
928                    format!("query strings do not support {}", atom.name()),
929                ));
930            }
931        }))
932    }
933}
934
935#[cold]
936fn unsupported_key() -> Error {
937    Error::new(
938        ErrorKind::UnsupportedType,
939        "keys of query strings must be strings, numbers or booleans",
940    )
941}