Skip to main content

ron/ser/
mod.rs

1use alloc::{borrow::Cow, string::String};
2use core::fmt;
3
4use serde::{ser, ser::Serialize};
5use serde_derive::{Deserialize, Serialize};
6use unicode_ident::is_xid_continue;
7
8use crate::{
9    error::{Error, Result},
10    extensions::Extensions,
11    options::Options,
12    parse::{is_ident_first_char, is_ident_raw_char, is_whitespace_char, LargeSInt, LargeUInt},
13};
14
15pub mod path_meta;
16
17mod raw;
18#[cfg(test)]
19mod tests;
20mod value;
21
22/// Serializes `value` into `writer`.
23///
24/// This function does not generate any newlines or nice formatting;
25/// if you want that, you can use [`to_writer_pretty`] instead.
26///
27/// `writer` is required to implement [`core::fmt::Write`]. To use [`std::io::Write`] instead,
28/// see [`Options::to_io_writer`](crate::options::Options::to_io_writer).
29pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
30where
31    W: fmt::Write,
32    T: ?Sized + Serialize,
33{
34    Options::default().to_writer(writer, value)
35}
36
37/// Serializes `value` into `writer` in a pretty way.
38///
39/// `writer` is required to implement [`core::fmt::Write`]. To use [`std::io::Write`] instead,
40/// see [`Options::to_io_writer_pretty`](crate::options::Options::to_io_writer_pretty).
41pub fn to_writer_pretty<W, T>(writer: W, value: &T, config: PrettyConfig) -> Result<()>
42where
43    W: fmt::Write,
44    T: ?Sized + Serialize,
45{
46    Options::default().to_writer_pretty(writer, value, config)
47}
48
49/// Serializes `value` and returns it as string.
50///
51/// This function does not generate any newlines or nice formatting;
52/// if you want that, you can use [`to_string_pretty`] instead.
53pub fn to_string<T>(value: &T) -> Result<String>
54where
55    T: ?Sized + Serialize,
56{
57    Options::default().to_string(value)
58}
59
60/// Serializes `value` in the recommended RON layout in a pretty way.
61pub fn to_string_pretty<T>(value: &T, config: PrettyConfig) -> Result<String>
62where
63    T: ?Sized + Serialize,
64{
65    Options::default().to_string_pretty(value, config)
66}
67
68/// Pretty serializer state
69struct Pretty {
70    indent: usize,
71}
72
73/// Pretty serializer configuration.
74///
75/// # Examples
76///
77/// ```
78/// use ron::ser::PrettyConfig;
79///
80/// let my_config = PrettyConfig::new()
81///     .depth_limit(4)
82///     // definitely superior (okay, just joking)
83///     .indentor("\t");
84/// ```
85#[allow(clippy::struct_excessive_bools)]
86#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
87#[serde(default)]
88#[non_exhaustive]
89pub struct PrettyConfig {
90    /// Limit the pretty-ness up to the given depth.
91    pub depth_limit: usize,
92    /// New line string
93    pub new_line: Cow<'static, str>,
94    /// Indentation string
95    pub indentor: Cow<'static, str>,
96    /// Separator string
97    pub separator: Cow<'static, str>,
98    // Whether to emit struct names
99    pub struct_names: bool,
100    /// Separate tuple members with indentation
101    pub separate_tuple_members: bool,
102    /// Enumerate array items in comments
103    pub enumerate_arrays: bool,
104    /// Enable extensions. Only configures `implicit_some`,
105    ///  `unwrap_newtypes`, and `unwrap_variant_newtypes` for now.
106    pub extensions: Extensions,
107    /// Enable compact arrays, which do not insert new lines and indentation
108    ///  between the elements of an array
109    pub compact_arrays: bool,
110    /// Whether to serialize strings as escaped strings,
111    ///  or fall back onto raw strings if necessary.
112    pub escape_strings: bool,
113    /// Enable compact structs, which do not insert new lines and indentation
114    ///  between the fields of a struct
115    pub compact_structs: bool,
116    /// Enable compact maps, which do not insert new lines and indentation
117    ///  between the entries of a struct
118    pub compact_maps: bool,
119    /// Enable explicit number type suffixes like `1u16`
120    pub number_suffixes: bool,
121    /// Additional path-based field metadata to serialize
122    pub path_meta: Option<path_meta::Field>,
123    /// Enable compact range syntax, e.g. `0..5` instead of `(start: 0, end: 5)`.
124    pub compact_ranges: bool,
125}
126
127impl PrettyConfig {
128    /// Creates a default [`PrettyConfig`].
129    #[must_use]
130    pub fn new() -> Self {
131        Self::default()
132    }
133
134    /// Limits the pretty-formatting based on the number of indentations.
135    /// I.e., with a depth limit of 5, starting with an element of depth
136    /// (indentation level) 6, everything will be put into the same line,
137    /// without pretty formatting.
138    ///
139    /// Default: [`usize::MAX`]
140    #[must_use]
141    pub fn depth_limit(mut self, depth_limit: usize) -> Self {
142        self.depth_limit = depth_limit;
143
144        self
145    }
146
147    /// Configures the newlines used for serialization.
148    ///
149    /// Default: `\r\n` on Windows, `\n` otherwise
150    #[must_use]
151    pub fn new_line(mut self, new_line: impl Into<Cow<'static, str>>) -> Self {
152        self.new_line = new_line.into();
153
154        self
155    }
156
157    /// Configures the string sequence used for indentation.
158    ///
159    /// Default: 4 spaces
160    #[must_use]
161    pub fn indentor(mut self, indentor: impl Into<Cow<'static, str>>) -> Self {
162        self.indentor = indentor.into();
163
164        self
165    }
166
167    /// Configures the string sequence used to separate items inline.
168    ///
169    /// Default: 1 space
170    #[must_use]
171    pub fn separator(mut self, separator: impl Into<Cow<'static, str>>) -> Self {
172        self.separator = separator.into();
173
174        self
175    }
176
177    /// Configures whether to emit struct names.
178    ///
179    /// See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent.
180    ///
181    /// Default: `false`
182    #[must_use]
183    pub fn struct_names(mut self, struct_names: bool) -> Self {
184        self.struct_names = struct_names;
185
186        self
187    }
188
189    /// Configures whether tuples are single- or multi-line.
190    /// If set to `true`, tuples will have their fields indented and in new
191    /// lines. If set to `false`, tuples will be serialized without any
192    /// newlines or indentations.
193    ///
194    /// Default: `false`
195    #[must_use]
196    pub fn separate_tuple_members(mut self, separate_tuple_members: bool) -> Self {
197        self.separate_tuple_members = separate_tuple_members;
198
199        self
200    }
201
202    /// Configures whether a comment shall be added to every array element,
203    /// indicating the index.
204    ///
205    /// Default: `false`
206    #[must_use]
207    pub fn enumerate_arrays(mut self, enumerate_arrays: bool) -> Self {
208        self.enumerate_arrays = enumerate_arrays;
209
210        self
211    }
212
213    /// Configures whether every array should be a single line (`true`)
214    /// or a multi line one (`false`).
215    ///
216    /// When `false`, `["a","b"]` will serialize to
217    /// ```
218    /// [
219    ///   "a",
220    ///   "b",
221    /// ]
222    /// # ;
223    /// ```
224    /// When `true`, `["a","b"]` will instead serialize to
225    /// ```
226    /// ["a","b"]
227    /// # ;
228    /// ```
229    ///
230    /// Default: `false`
231    #[must_use]
232    pub fn compact_arrays(mut self, compact_arrays: bool) -> Self {
233        self.compact_arrays = compact_arrays;
234
235        self
236    }
237
238    /// Configures extensions
239    ///
240    /// Default: [`Extensions::empty()`]
241    #[must_use]
242    pub fn extensions(mut self, extensions: Extensions) -> Self {
243        self.extensions = extensions;
244
245        self
246    }
247
248    /// Configures whether strings should be serialized using escapes (true)
249    /// or fall back to raw strings if the string contains a `"` (false).
250    ///
251    /// When `true`, `"a\nb"` will serialize to
252    /// ```
253    /// "a\nb"
254    /// # ;
255    /// ```
256    /// When `false`, `"a\nb"` will instead serialize to
257    /// ```
258    /// "a
259    /// b"
260    /// # ;
261    /// ```
262    ///
263    /// Default: `true`
264    #[must_use]
265    pub fn escape_strings(mut self, escape_strings: bool) -> Self {
266        self.escape_strings = escape_strings;
267
268        self
269    }
270
271    /// Configures whether every struct should be a single line (`true`)
272    /// or a multi line one (`false`).
273    ///
274    /// When `false`, `Struct { a: 4, b: 2 }` will serialize to
275    /// ```ignore
276    /// Struct(
277    ///     a: 4,
278    ///     b: 2,
279    /// )
280    /// # ;
281    /// ```
282    /// When `true`, `Struct { a: 4, b: 2 }` will instead serialize to
283    /// ```ignore
284    /// Struct(a: 4, b: 2)
285    /// # ;
286    /// ```
287    ///
288    /// Default: `false`
289    #[must_use]
290    pub fn compact_structs(mut self, compact_structs: bool) -> Self {
291        self.compact_structs = compact_structs;
292
293        self
294    }
295
296    /// Configures whether every map should be a single line (`true`)
297    /// or a multi line one (`false`).
298    ///
299    /// When `false`, a map with entries `{ "a": 4, "b": 2 }` will serialize to
300    /// ```ignore
301    /// {
302    ///     "a": 4,
303    ///     "b": 2,
304    /// }
305    /// # ;
306    /// ```
307    /// When `true`, a map with entries `{ "a": 4, "b": 2 }` will instead
308    /// serialize to
309    /// ```ignore
310    /// {"a": 4, "b": 2}
311    /// # ;
312    /// ```
313    ///
314    /// Default: `false`
315    #[must_use]
316    pub fn compact_maps(mut self, compact_maps: bool) -> Self {
317        self.compact_maps = compact_maps;
318
319        self
320    }
321
322    /// Configures whether numbers should be printed without (`false`) or
323    /// with (`true`) their explicit type suffixes.
324    ///
325    /// When `false`, the integer `12345u16` will serialize to
326    /// ```ignore
327    /// 12345
328    /// # ;
329    /// ```
330    /// and the float `12345.6789f64` will serialize to
331    /// ```ignore
332    /// 12345.6789
333    /// # ;
334    /// ```
335    /// When `true`, the integer `12345u16` will serialize to
336    /// ```ignore
337    /// 12345u16
338    /// # ;
339    /// ```
340    /// and the float `12345.6789f64` will serialize to
341    /// ```ignore
342    /// 12345.6789f64
343    /// # ;
344    /// ```
345    ///
346    /// Default: `false`
347    #[must_use]
348    pub fn number_suffixes(mut self, number_suffixes: bool) -> Self {
349        self.number_suffixes = number_suffixes;
350
351        self
352    }
353
354    /// Configures whether ranges should be serialized using compact syntax (`true`)
355    /// or as regular structs (`false`).
356    ///
357    /// Note: compact range syntax is only used when the range bounds are numeric
358    /// values. If the bounds are non-numeric, the range will fall back to the
359    /// regular struct representation regardless of this setting.
360    ///
361    /// When `false`, `0..5` will serialize to
362    /// ```ignore
363    /// (
364    ///     start: 0,
365    ///     end: 5,
366    /// )
367    /// # ;
368    /// ```
369    /// When `true`, `0..5` will instead serialize to
370    /// ```ignore
371    /// 0..5
372    /// # ;
373    /// ```
374    /// and `1..=3` will serialize to
375    /// ```ignore
376    /// 1..=3
377    /// # ;
378    /// ```
379    ///
380    /// Default: `false`
381    #[must_use]
382    pub fn compact_ranges(mut self, compact_ranges: bool) -> Self {
383        self.compact_ranges = compact_ranges;
384        self
385    }
386}
387
388impl Default for PrettyConfig {
389    fn default() -> Self {
390        PrettyConfig {
391            depth_limit: usize::MAX,
392            new_line: if cfg!(not(target_os = "windows")) {
393                Cow::Borrowed("\n")
394            } else {
395                Cow::Borrowed("\r\n") // GRCOV_EXCL_LINE
396            },
397            indentor: Cow::Borrowed("    "),
398            separator: Cow::Borrowed(" "),
399            struct_names: false,
400            separate_tuple_members: false,
401            enumerate_arrays: false,
402            extensions: Extensions::empty(),
403            compact_arrays: false,
404            escape_strings: true,
405            compact_structs: false,
406            compact_maps: false,
407            number_suffixes: false,
408            path_meta: None,
409            compact_ranges: false,
410        }
411    }
412}
413
414/// The RON serializer.
415///
416/// You can just use [`to_string`] for serializing a value.
417/// If you want it pretty-printed, take a look at [`to_string_pretty`].
418pub struct Serializer<W: fmt::Write> {
419    output: W,
420    pretty: Option<(PrettyConfig, Pretty)>,
421    default_extensions: Extensions,
422    is_empty: Option<bool>,
423    newtype_variant: bool,
424    recursion_limit: Option<usize>,
425    // Tracks the number of opened implicit `Some`s, set to 0 on backtracking
426    implicit_some_depth: usize,
427}
428
429fn indent<W: fmt::Write>(output: &mut W, config: &PrettyConfig, pretty: &Pretty) -> fmt::Result {
430    if pretty.indent <= config.depth_limit {
431        for _ in 0..pretty.indent {
432            output.write_str(&config.indentor)?;
433        }
434    }
435    Ok(())
436}
437
438impl<W: fmt::Write> Serializer<W> {
439    /// Creates a new [`Serializer`].
440    ///
441    /// Most of the time you can just use [`to_string`] or
442    /// [`to_string_pretty`].
443    pub fn new(writer: W, config: Option<PrettyConfig>) -> Result<Self> {
444        Self::with_options(writer, config, &Options::default())
445    }
446
447    /// Creates a new [`Serializer`].
448    ///
449    /// Most of the time you can just use [`to_string`] or
450    /// [`to_string_pretty`].
451    pub fn with_options(
452        mut writer: W,
453        config: Option<PrettyConfig>,
454        options: &Options,
455    ) -> Result<Self> {
456        if let Some(conf) = &config {
457            if !conf.new_line.chars().all(is_whitespace_char) {
458                return Err(Error::Message(String::from(
459                    "Invalid non-whitespace `PrettyConfig::new_line`",
460                )));
461            }
462            if !conf.indentor.chars().all(is_whitespace_char) {
463                return Err(Error::Message(String::from(
464                    "Invalid non-whitespace `PrettyConfig::indentor`",
465                )));
466            }
467            if !conf.separator.chars().all(is_whitespace_char) {
468                return Err(Error::Message(String::from(
469                    "Invalid non-whitespace `PrettyConfig::separator`",
470                )));
471            }
472
473            let non_default_extensions = !options.default_extensions;
474
475            for (extension_name, _) in (non_default_extensions & conf.extensions).iter_names() {
476                write!(writer, "#![enable({})]", extension_name.to_lowercase())?;
477                writer.write_str(&conf.new_line)?;
478            }
479        };
480        Ok(Serializer {
481            output: writer,
482            pretty: config.map(|conf| (conf, Pretty { indent: 0 })),
483            default_extensions: options.default_extensions,
484            is_empty: None,
485            newtype_variant: false,
486            recursion_limit: options.recursion_limit,
487            implicit_some_depth: 0,
488        })
489    }
490
491    /// Unwrap the `Writer` from the `Serializer`.
492    #[inline]
493    pub fn into_inner(self) -> W {
494        self.output
495    }
496
497    fn separate_tuple_members(&self) -> bool {
498        self.pretty
499            .as_ref()
500            .map_or(false, |(ref config, _)| config.separate_tuple_members)
501    }
502
503    fn compact_arrays(&self) -> bool {
504        self.pretty
505            .as_ref()
506            .map_or(false, |(ref config, _)| config.compact_arrays)
507    }
508
509    fn compact_structs(&self) -> bool {
510        self.pretty
511            .as_ref()
512            .map_or(false, |(ref config, _)| config.compact_structs)
513    }
514
515    fn compact_maps(&self) -> bool {
516        self.pretty
517            .as_ref()
518            .map_or(false, |(ref config, _)| config.compact_maps)
519    }
520
521    fn number_suffixes(&self) -> bool {
522        self.pretty
523            .as_ref()
524            .map_or(false, |(ref config, _)| config.number_suffixes)
525    }
526
527    fn compact_ranges(&self) -> bool {
528        self.pretty
529            .as_ref()
530            .map_or(false, |(ref config, _)| config.compact_ranges)
531    }
532
533    fn extensions(&self) -> Extensions {
534        self.default_extensions
535            | self
536                .pretty
537                .as_ref()
538                .map_or(Extensions::empty(), |(ref config, _)| config.extensions)
539    }
540
541    fn escape_strings(&self) -> bool {
542        self.pretty
543            .as_ref()
544            .map_or(true, |(ref config, _)| config.escape_strings)
545    }
546
547    fn start_indent(&mut self) -> Result<()> {
548        if let Some((ref config, ref mut pretty)) = self.pretty {
549            pretty.indent += 1;
550            if pretty.indent <= config.depth_limit {
551                let is_empty = self.is_empty.unwrap_or(false);
552
553                if !is_empty {
554                    self.output.write_str(&config.new_line)?;
555                }
556            }
557        }
558        Ok(())
559    }
560
561    fn indent(&mut self) -> fmt::Result {
562        if let Some((ref config, ref pretty)) = self.pretty {
563            indent(&mut self.output, config, pretty)?;
564        }
565        Ok(())
566    }
567
568    fn end_indent(&mut self) -> fmt::Result {
569        if let Some((ref config, ref mut pretty)) = self.pretty {
570            if pretty.indent <= config.depth_limit {
571                let is_empty = self.is_empty.unwrap_or(false);
572
573                if !is_empty {
574                    for _ in 1..pretty.indent {
575                        self.output.write_str(&config.indentor)?;
576                    }
577                }
578            }
579            pretty.indent -= 1;
580
581            self.is_empty = None;
582        }
583        Ok(())
584    }
585
586    fn serialize_escaped_str(&mut self, value: &str) -> fmt::Result {
587        self.output.write_char('"')?;
588        let mut scalar = [0u8; 4];
589        for c in value.chars().flat_map(char::escape_debug) {
590            self.output.write_str(c.encode_utf8(&mut scalar))?;
591        }
592        self.output.write_char('"')?;
593        Ok(())
594    }
595
596    fn serialize_unescaped_or_raw_str(&mut self, value: &str) -> fmt::Result {
597        if value.contains('"') || value.contains('\\') {
598            let (_, num_consecutive_hashes) =
599                value.chars().fold((0, 0), |(count, max), c| match c {
600                    '#' => (count + 1, max.max(count + 1)),
601                    _ => (0_usize, max),
602                });
603            let hashes: String = "#".repeat(num_consecutive_hashes + 1);
604            self.output.write_char('r')?;
605            self.output.write_str(&hashes)?;
606            self.output.write_char('"')?;
607            self.output.write_str(value)?;
608            self.output.write_char('"')?;
609            self.output.write_str(&hashes)?;
610        } else {
611            self.output.write_char('"')?;
612            self.output.write_str(value)?;
613            self.output.write_char('"')?;
614        }
615        Ok(())
616    }
617
618    fn serialize_escaped_byte_str(&mut self, value: &[u8]) -> fmt::Result {
619        self.output.write_str("b\"")?;
620        for c in value.iter().flat_map(|c| core::ascii::escape_default(*c)) {
621            self.output.write_char(char::from(c))?;
622        }
623        self.output.write_char('"')?;
624        Ok(())
625    }
626
627    fn serialize_unescaped_or_raw_byte_str(&mut self, value: &str) -> fmt::Result {
628        if value.contains('"') || value.contains('\\') {
629            let (_, num_consecutive_hashes) =
630                value.chars().fold((0, 0), |(count, max), c| match c {
631                    '#' => (count + 1, max.max(count + 1)),
632                    _ => (0_usize, max),
633                });
634            let hashes: String = "#".repeat(num_consecutive_hashes + 1);
635            self.output.write_str("br")?;
636            self.output.write_str(&hashes)?;
637            self.output.write_char('"')?;
638            self.output.write_str(value)?;
639            self.output.write_char('"')?;
640            self.output.write_str(&hashes)?;
641        } else {
642            self.output.write_str("b\"")?;
643            self.output.write_str(value)?;
644            self.output.write_char('"')?;
645        }
646        Ok(())
647    }
648
649    fn serialize_sint(&mut self, value: impl Into<LargeSInt>, suffix: &str) -> Result<()> {
650        // TODO optimize
651        write!(self.output, "{}", value.into())?;
652
653        if self.number_suffixes() {
654            write!(self.output, "{}", suffix)?;
655        }
656
657        Ok(())
658    }
659
660    fn serialize_uint(&mut self, value: impl Into<LargeUInt>, suffix: &str) -> Result<()> {
661        // TODO optimize
662        write!(self.output, "{}", value.into())?;
663
664        if self.number_suffixes() {
665            write!(self.output, "{}", suffix)?;
666        }
667
668        Ok(())
669    }
670
671    fn write_identifier(&mut self, name: &str) -> Result<()> {
672        self.validate_identifier(name)?;
673        let mut chars = name.chars();
674        if !chars.next().map_or(false, is_ident_first_char)
675            || !chars.all(is_xid_continue)
676            || [
677                "true", "false", "Some", "None", "inf", "inff32", "inff64", "NaN", "NaNf32",
678                "NaNf64",
679            ]
680            .contains(&name)
681        {
682            self.output.write_str("r#")?;
683        }
684        self.output.write_str(name)?;
685        Ok(())
686    }
687
688    #[allow(clippy::unused_self)]
689    fn validate_identifier(&self, name: &str) -> Result<()> {
690        if name.is_empty() || !name.chars().all(is_ident_raw_char) {
691            return Err(Error::InvalidIdentifier(name.into()));
692        }
693        Ok(())
694    }
695
696    /// Checks if struct names should be emitted
697    ///
698    /// Note that when using the `explicit_struct_names` extension, this method will use an OR operation on the extension and the [`PrettyConfig::struct_names`] option. See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent.
699    fn struct_names(&self) -> bool {
700        self.extensions()
701            .contains(Extensions::EXPLICIT_STRUCT_NAMES)
702            || self
703                .pretty
704                .as_ref()
705                .map_or(false, |(pc, _)| pc.struct_names)
706    }
707}
708
709macro_rules! guard_recursion {
710    ($self:expr => $expr:expr) => {{
711        if let Some(limit) = &mut $self.recursion_limit {
712            if let Some(new_limit) = limit.checked_sub(1) {
713                *limit = new_limit;
714            } else {
715                return Err(Error::ExceededRecursionLimit);
716            }
717        }
718
719        let result = $expr;
720
721        if let Some(limit) = &mut $self.recursion_limit {
722            *limit = limit.saturating_add(1);
723        }
724
725        result
726    }};
727}
728
729impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
730    type Error = Error;
731    type Ok = ();
732    type SerializeMap = Compound<'a, W>;
733    type SerializeSeq = Compound<'a, W>;
734    type SerializeStruct = Compound<'a, W>;
735    type SerializeStructVariant = Compound<'a, W>;
736    type SerializeTuple = Compound<'a, W>;
737    type SerializeTupleStruct = Compound<'a, W>;
738    type SerializeTupleVariant = Compound<'a, W>;
739
740    fn serialize_bool(self, v: bool) -> Result<()> {
741        self.output.write_str(if v { "true" } else { "false" })?;
742        Ok(())
743    }
744
745    fn serialize_i8(self, v: i8) -> Result<()> {
746        self.serialize_sint(v, "i8")
747    }
748
749    fn serialize_i16(self, v: i16) -> Result<()> {
750        self.serialize_sint(v, "i16")
751    }
752
753    fn serialize_i32(self, v: i32) -> Result<()> {
754        self.serialize_sint(v, "i32")
755    }
756
757    fn serialize_i64(self, v: i64) -> Result<()> {
758        self.serialize_sint(v, "i64")
759    }
760
761    #[cfg(feature = "integer128")]
762    fn serialize_i128(self, v: i128) -> Result<()> {
763        self.serialize_sint(v, "i128")
764    }
765
766    fn serialize_u8(self, v: u8) -> Result<()> {
767        self.serialize_uint(v, "u8")
768    }
769
770    fn serialize_u16(self, v: u16) -> Result<()> {
771        self.serialize_uint(v, "u16")
772    }
773
774    fn serialize_u32(self, v: u32) -> Result<()> {
775        self.serialize_uint(v, "u32")
776    }
777
778    fn serialize_u64(self, v: u64) -> Result<()> {
779        self.serialize_uint(v, "u64")
780    }
781
782    #[cfg(feature = "integer128")]
783    fn serialize_u128(self, v: u128) -> Result<()> {
784        self.serialize_uint(v, "u128")
785    }
786
787    fn serialize_f32(self, v: f32) -> Result<()> {
788        if v.is_nan() && v.is_sign_negative() {
789            write!(self.output, "-")?;
790        }
791
792        // `Debug` emits the shortest representation that round-trips, using
793        // exponent notation for very large or small magnitudes (e.g. `1e300`)
794        // and always including a `.0` or exponent for finite values, so they
795        // are never parsed back as integers.
796        write!(self.output, "{:?}", v)?;
797
798        if self.number_suffixes() {
799            write!(self.output, "f32")?;
800        }
801
802        Ok(())
803    }
804
805    fn serialize_f64(self, v: f64) -> Result<()> {
806        if v.is_nan() && v.is_sign_negative() {
807            write!(self.output, "-")?;
808        }
809
810        // `Debug` emits the shortest representation that round-trips, using
811        // exponent notation for very large or small magnitudes (e.g. `1e300`)
812        // and always including a `.0` or exponent for finite values, so they
813        // are never parsed back as integers.
814        write!(self.output, "{:?}", v)?;
815
816        if self.number_suffixes() {
817            write!(self.output, "f64")?;
818        }
819
820        Ok(())
821    }
822
823    fn serialize_char(self, v: char) -> Result<()> {
824        self.output.write_char('\'')?;
825        if v == '\\' || v == '\'' {
826            self.output.write_char('\\')?;
827        }
828        write!(self.output, "{}", v)?;
829        self.output.write_char('\'')?;
830        Ok(())
831    }
832
833    fn serialize_str(self, v: &str) -> Result<()> {
834        if self.escape_strings() {
835            self.serialize_escaped_str(v)?;
836        } else {
837            self.serialize_unescaped_or_raw_str(v)?;
838        }
839
840        Ok(())
841    }
842
843    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
844        // We need to fall back to escaping if the byte string would be invalid UTF-8
845        if !self.escape_strings() {
846            if let Ok(v) = core::str::from_utf8(v) {
847                return self
848                    .serialize_unescaped_or_raw_byte_str(v)
849                    .map_err(Error::from);
850            }
851        }
852
853        self.serialize_escaped_byte_str(v)?;
854
855        Ok(())
856    }
857
858    fn serialize_none(self) -> Result<()> {
859        // We no longer need to keep track of the depth
860        let implicit_some_depth = self.implicit_some_depth;
861        self.implicit_some_depth = 0;
862
863        for _ in 0..implicit_some_depth {
864            self.output.write_str("Some(")?;
865        }
866        self.output.write_str("None")?;
867        for _ in 0..implicit_some_depth {
868            self.output.write_char(')')?;
869        }
870
871        Ok(())
872    }
873
874    fn serialize_some<T>(self, value: &T) -> Result<()>
875    where
876        T: ?Sized + Serialize,
877    {
878        let implicit_some = self.extensions().contains(Extensions::IMPLICIT_SOME);
879        if implicit_some {
880            self.implicit_some_depth += 1;
881        } else {
882            self.newtype_variant = self
883                .extensions()
884                .contains(Extensions::UNWRAP_VARIANT_NEWTYPES);
885            self.output.write_str("Some(")?;
886        }
887        guard_recursion! { self => value.serialize(&mut *self)? };
888        if implicit_some {
889            self.implicit_some_depth = 0;
890        } else {
891            self.output.write_char(')')?;
892            self.newtype_variant = false;
893        }
894
895        Ok(())
896    }
897
898    fn serialize_unit(self) -> Result<()> {
899        if !self.newtype_variant {
900            self.output.write_str("()")?;
901        }
902
903        Ok(())
904    }
905
906    fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
907        if self.compact_ranges() && name == "RangeFull" {
908            self.output.write_str("..")?;
909            return Ok(());
910        }
911
912        if self.struct_names() && !self.newtype_variant {
913            self.write_identifier(name)?;
914
915            Ok(())
916        } else {
917            self.validate_identifier(name)?;
918            self.serialize_unit()
919        }
920    }
921
922    fn serialize_unit_variant(
923        self,
924        name: &'static str,
925        _variant_index: u32,
926        variant: &'static str,
927    ) -> Result<()> {
928        self.validate_identifier(name)?;
929        self.write_identifier(variant)?;
930
931        Ok(())
932    }
933
934    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
935    where
936        T: ?Sized + Serialize,
937    {
938        if name == crate::value::raw::RAW_VALUE_TOKEN {
939            let implicit_some_depth = self.implicit_some_depth;
940            self.implicit_some_depth = 0;
941
942            for _ in 0..implicit_some_depth {
943                self.output.write_str("Some(")?;
944            }
945
946            guard_recursion! { self => value.serialize(raw::Serializer::new(self)) }?;
947
948            for _ in 0..implicit_some_depth {
949                self.output.write_char(')')?;
950            }
951
952            return Ok(());
953        }
954
955        if self.extensions().contains(Extensions::UNWRAP_NEWTYPES) || self.newtype_variant {
956            self.newtype_variant = false;
957
958            self.validate_identifier(name)?;
959
960            return guard_recursion! { self => value.serialize(&mut *self) };
961        }
962
963        if self.struct_names() {
964            self.write_identifier(name)?;
965        } else {
966            self.validate_identifier(name)?;
967        }
968
969        self.implicit_some_depth = 0;
970
971        self.output.write_char('(')?;
972        guard_recursion! { self => value.serialize(&mut *self)? };
973        self.output.write_char(')')?;
974
975        Ok(())
976    }
977
978    fn serialize_newtype_variant<T>(
979        self,
980        name: &'static str,
981        _variant_index: u32,
982        variant: &'static str,
983        value: &T,
984    ) -> Result<()>
985    where
986        T: ?Sized + Serialize,
987    {
988        self.validate_identifier(name)?;
989        self.write_identifier(variant)?;
990        self.output.write_char('(')?;
991
992        self.newtype_variant = self
993            .extensions()
994            .contains(Extensions::UNWRAP_VARIANT_NEWTYPES);
995        self.implicit_some_depth = 0;
996
997        guard_recursion! { self => value.serialize(&mut *self)? };
998
999        self.newtype_variant = false;
1000
1001        self.output.write_char(')')?;
1002        Ok(())
1003    }
1004
1005    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
1006        self.newtype_variant = false;
1007        self.implicit_some_depth = 0;
1008
1009        self.output.write_char('[')?;
1010
1011        if !self.compact_arrays() {
1012            if let Some(len) = len {
1013                self.is_empty = Some(len == 0);
1014            }
1015
1016            self.start_indent()?;
1017        }
1018
1019        Ok(Compound::new(self, false))
1020    }
1021
1022    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
1023        let old_newtype_variant = self.newtype_variant;
1024        self.newtype_variant = false;
1025        self.implicit_some_depth = 0;
1026
1027        if !old_newtype_variant {
1028            self.output.write_char('(')?;
1029        }
1030
1031        if self.separate_tuple_members() {
1032            self.is_empty = Some(len == 0);
1033
1034            self.start_indent()?;
1035        }
1036
1037        Ok(Compound::new(self, old_newtype_variant))
1038    }
1039
1040    fn serialize_tuple_struct(
1041        self,
1042        name: &'static str,
1043        len: usize,
1044    ) -> Result<Self::SerializeTupleStruct> {
1045        if self.struct_names() && !self.newtype_variant {
1046            self.write_identifier(name)?;
1047        } else {
1048            self.validate_identifier(name)?;
1049        }
1050
1051        self.serialize_tuple(len)
1052    }
1053
1054    fn serialize_tuple_variant(
1055        self,
1056        name: &'static str,
1057        _variant_index: u32,
1058        variant: &'static str,
1059        len: usize,
1060    ) -> Result<Self::SerializeTupleVariant> {
1061        self.newtype_variant = false;
1062        self.implicit_some_depth = 0;
1063
1064        self.validate_identifier(name)?;
1065        self.write_identifier(variant)?;
1066        self.output.write_char('(')?;
1067
1068        if self.separate_tuple_members() {
1069            self.is_empty = Some(len == 0);
1070
1071            self.start_indent()?;
1072        }
1073
1074        Ok(Compound::new(self, false))
1075    }
1076
1077    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
1078        self.newtype_variant = false;
1079        self.implicit_some_depth = 0;
1080
1081        self.output.write_char('{')?;
1082
1083        if !self.compact_maps() {
1084            if let Some(len) = len {
1085                self.is_empty = Some(len == 0);
1086            }
1087
1088            self.start_indent()?;
1089        }
1090
1091        Ok(Compound::new(self, false))
1092    }
1093
1094    fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
1095        let old_newtype_variant = self.newtype_variant;
1096        if self.compact_ranges()
1097            && ((len == 2 && (name == "Range" || name == "RangeInclusive"))
1098                || (len == 1
1099                    && (name == "RangeFrom" || name == "RangeTo" || name == "RangeToInclusive")))
1100        {
1101            self.newtype_variant = false;
1102            self.implicit_some_depth = 0;
1103            return Ok(Compound::new_range(
1104                self,
1105                name,
1106                old_newtype_variant,
1107                if name == "RangeInclusive" {
1108                    RangeKind::RangeInclusive
1109                } else if name == "RangeFrom" {
1110                    RangeKind::RangeFrom
1111                } else if name == "RangeTo" {
1112                    RangeKind::RangeTo
1113                } else if name == "RangeToInclusive" {
1114                    RangeKind::RangeToInclusive
1115                } else {
1116                    RangeKind::Range
1117                },
1118            ));
1119        }
1120
1121        self.newtype_variant = false;
1122        self.implicit_some_depth = 0;
1123
1124        if old_newtype_variant {
1125            self.validate_identifier(name)?;
1126        } else {
1127            if self.struct_names() {
1128                self.write_identifier(name)?;
1129            } else {
1130                self.validate_identifier(name)?;
1131            }
1132            self.output.write_char('(')?;
1133        }
1134
1135        if !self.compact_structs() {
1136            self.is_empty = Some(len == 0);
1137            self.start_indent()?;
1138        }
1139
1140        Ok(Compound::new(self, old_newtype_variant))
1141    }
1142
1143    fn serialize_struct_variant(
1144        self,
1145        name: &'static str,
1146        _variant_index: u32,
1147        variant: &'static str,
1148        len: usize,
1149    ) -> Result<Self::SerializeStructVariant> {
1150        self.newtype_variant = false;
1151        self.implicit_some_depth = 0;
1152
1153        self.validate_identifier(name)?;
1154        self.write_identifier(variant)?;
1155        self.output.write_char('(')?;
1156
1157        if !self.compact_structs() {
1158            self.is_empty = Some(len == 0);
1159            self.start_indent()?;
1160        }
1161
1162        Ok(Compound::new(self, false))
1163    }
1164}
1165
1166enum State {
1167    First,
1168    Rest,
1169}
1170
1171#[doc(hidden)]
1172pub struct Compound<'a, W: fmt::Write> {
1173    ser: &'a mut Serializer<W>,
1174    state: State,
1175    newtype_variant: bool,
1176    sequence_index: usize,
1177    range: Option<RangeCompound>,
1178}
1179
1180impl<'a, W: fmt::Write> Compound<'a, W> {
1181    fn new(ser: &'a mut Serializer<W>, newtype_variant: bool) -> Self {
1182        Compound {
1183            ser,
1184            state: State::First,
1185            newtype_variant,
1186            sequence_index: 0,
1187            range: None,
1188        }
1189    }
1190
1191    fn new_range(
1192        ser: &'a mut Serializer<W>,
1193        name: &'static str,
1194        newtype_variant: bool,
1195        kind: RangeKind,
1196    ) -> Self {
1197        Compound {
1198            ser,
1199            state: State::First,
1200            newtype_variant: false,
1201            sequence_index: 0,
1202            range: Some(RangeCompound::new(name, newtype_variant, kind)),
1203        }
1204    }
1205}
1206
1207enum RangeKind {
1208    Range,
1209    RangeInclusive,
1210    RangeFrom,
1211    RangeTo,
1212    RangeToInclusive,
1213}
1214
1215struct RangeCompound {
1216    name: &'static str,
1217    // Whether the range is the content of an unwrapped newtype variant, which
1218    // the struct form fallback must then write without its own parentheses.
1219    newtype_variant: bool,
1220    kind: RangeKind,
1221    // Stores (field_key, number) so the actual key is preserved through fallback replay.
1222    first: Option<(&'static str, crate::value::Number)>,
1223    second: Option<(&'static str, crate::value::Number)>,
1224    fallback: bool,
1225}
1226
1227impl RangeCompound {
1228    fn new(name: &'static str, newtype_variant: bool, kind: RangeKind) -> Self {
1229        RangeCompound {
1230            name,
1231            newtype_variant,
1232            kind,
1233            first: None,
1234            second: None,
1235            fallback: false,
1236        }
1237    }
1238
1239    /// Try to serialize `value` as a number into a String buffer.
1240    /// Returns `Some(s)` if numeric, `None` otherwise.
1241    fn try_serialize_number<T>(value: &T) -> Option<crate::value::Number>
1242    where
1243        T: ?Sized + Serialize,
1244    {
1245        value.serialize(crate::value::NumberSerializer).ok()
1246    }
1247}
1248
1249impl<'a, W: fmt::Write> Drop for Compound<'a, W> {
1250    fn drop(&mut self) {
1251        if let Some(limit) = &mut self.ser.recursion_limit {
1252            *limit = limit.saturating_add(1);
1253        }
1254    }
1255}
1256
1257impl<'a, W: fmt::Write> ser::SerializeSeq for Compound<'a, W> {
1258    type Error = Error;
1259    type Ok = ();
1260
1261    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
1262    where
1263        T: ?Sized + Serialize,
1264    {
1265        if let State::First = self.state {
1266            self.state = State::Rest;
1267        } else {
1268            self.ser.output.write_char(',')?;
1269            if let Some((ref config, ref mut pretty)) = self.ser.pretty {
1270                if pretty.indent <= config.depth_limit && !config.compact_arrays {
1271                    self.ser.output.write_str(&config.new_line)?;
1272                } else {
1273                    self.ser.output.write_str(&config.separator)?;
1274                }
1275            }
1276        }
1277
1278        if !self.ser.compact_arrays() {
1279            self.ser.indent()?;
1280        }
1281
1282        if let Some((ref mut config, ref mut pretty)) = self.ser.pretty {
1283            if pretty.indent <= config.depth_limit && config.enumerate_arrays {
1284                write!(self.ser.output, "/*[{}]*/ ", self.sequence_index)?;
1285                self.sequence_index += 1;
1286            }
1287        }
1288
1289        guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
1290
1291        Ok(())
1292    }
1293
1294    fn end(self) -> Result<()> {
1295        if let State::Rest = self.state {
1296            if let Some((ref config, ref mut pretty)) = self.ser.pretty {
1297                if pretty.indent <= config.depth_limit && !config.compact_arrays {
1298                    self.ser.output.write_char(',')?;
1299                    self.ser.output.write_str(&config.new_line)?;
1300                }
1301            }
1302        }
1303
1304        if !self.ser.compact_arrays() {
1305            self.ser.end_indent()?;
1306        }
1307
1308        // seq always disables `self.newtype_variant`
1309        self.ser.output.write_char(']')?;
1310        Ok(())
1311    }
1312}
1313
1314impl<'a, W: fmt::Write> ser::SerializeTuple for Compound<'a, W> {
1315    type Error = Error;
1316    type Ok = ();
1317
1318    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
1319    where
1320        T: ?Sized + Serialize,
1321    {
1322        if let State::First = self.state {
1323            self.state = State::Rest;
1324        } else {
1325            self.ser.output.write_char(',')?;
1326            if let Some((ref config, ref pretty)) = self.ser.pretty {
1327                if pretty.indent <= config.depth_limit && self.ser.separate_tuple_members() {
1328                    self.ser.output.write_str(&config.new_line)?;
1329                } else {
1330                    self.ser.output.write_str(&config.separator)?;
1331                }
1332            }
1333        }
1334
1335        if self.ser.separate_tuple_members() {
1336            self.ser.indent()?;
1337        }
1338
1339        guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
1340
1341        Ok(())
1342    }
1343
1344    fn end(self) -> Result<()> {
1345        if let State::Rest = self.state {
1346            if let Some((ref config, ref pretty)) = self.ser.pretty {
1347                if self.ser.separate_tuple_members() && pretty.indent <= config.depth_limit {
1348                    self.ser.output.write_char(',')?;
1349                    self.ser.output.write_str(&config.new_line)?;
1350                }
1351            }
1352        }
1353        if self.ser.separate_tuple_members() {
1354            self.ser.end_indent()?;
1355        }
1356
1357        if !self.newtype_variant {
1358            self.ser.output.write_char(')')?;
1359        }
1360
1361        Ok(())
1362    }
1363}
1364
1365// Same thing but for tuple structs.
1366impl<'a, W: fmt::Write> ser::SerializeTupleStruct for Compound<'a, W> {
1367    type Error = Error;
1368    type Ok = ();
1369
1370    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
1371    where
1372        T: ?Sized + Serialize,
1373    {
1374        ser::SerializeTuple::serialize_element(self, value)
1375    }
1376
1377    fn end(self) -> Result<()> {
1378        ser::SerializeTuple::end(self)
1379    }
1380}
1381
1382impl<'a, W: fmt::Write> ser::SerializeTupleVariant for Compound<'a, W> {
1383    type Error = Error;
1384    type Ok = ();
1385
1386    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
1387    where
1388        T: ?Sized + Serialize,
1389    {
1390        ser::SerializeTuple::serialize_element(self, value)
1391    }
1392
1393    fn end(self) -> Result<()> {
1394        ser::SerializeTuple::end(self)
1395    }
1396}
1397
1398impl<'a, W: fmt::Write> ser::SerializeMap for Compound<'a, W> {
1399    type Error = Error;
1400    type Ok = ();
1401
1402    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
1403    where
1404        T: ?Sized + Serialize,
1405    {
1406        if let State::First = self.state {
1407            self.state = State::Rest;
1408        } else {
1409            self.ser.output.write_char(',')?;
1410
1411            if let Some((ref config, ref pretty)) = self.ser.pretty {
1412                if pretty.indent <= config.depth_limit && !config.compact_maps {
1413                    self.ser.output.write_str(&config.new_line)?;
1414                } else {
1415                    self.ser.output.write_str(&config.separator)?;
1416                }
1417            }
1418        }
1419
1420        if !self.ser.compact_maps() {
1421            self.ser.indent()?;
1422        }
1423
1424        guard_recursion! { self.ser => key.serialize(&mut *self.ser) }
1425    }
1426
1427    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
1428    where
1429        T: ?Sized + Serialize,
1430    {
1431        self.ser.output.write_char(':')?;
1432
1433        if let Some((ref config, _)) = self.ser.pretty {
1434            self.ser.output.write_str(&config.separator)?;
1435        }
1436
1437        guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
1438
1439        Ok(())
1440    }
1441
1442    fn end(self) -> Result<()> {
1443        if let State::Rest = self.state {
1444            if let Some((ref config, ref pretty)) = self.ser.pretty {
1445                if pretty.indent <= config.depth_limit && !config.compact_maps {
1446                    self.ser.output.write_char(',')?;
1447                    self.ser.output.write_str(&config.new_line)?;
1448                }
1449            }
1450        }
1451
1452        if !self.ser.compact_maps() {
1453            self.ser.end_indent()?;
1454        }
1455
1456        // map always disables `self.newtype_variant`
1457        self.ser.output.write_char('}')?;
1458        Ok(())
1459    }
1460}
1461
1462impl<'a, W: fmt::Write> ser::SerializeStruct for Compound<'a, W> {
1463    type Error = Error;
1464    type Ok = ();
1465
1466    #[allow(clippy::too_many_lines)]
1467    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
1468    where
1469        T: ?Sized + Serialize,
1470    {
1471        if let Some(ref mut range) = self.range {
1472            if !range.fallback {
1473                match RangeCompound::try_serialize_number(value) {
1474                    Some(s) => {
1475                        // Validate that the field key matches what this range variant expects,
1476                        // and that we haven't received more fields than the variant allows.
1477                        let expected_key = match range.kind {
1478                            RangeKind::RangeTo | RangeKind::RangeToInclusive => {
1479                                if range.first.is_none() {
1480                                    "end"
1481                                } else {
1482                                    ""
1483                                }
1484                            }
1485                            _ => {
1486                                if range.first.is_none() {
1487                                    "start"
1488                                } else {
1489                                    "end"
1490                                }
1491                            }
1492                        };
1493
1494                        let max_fields = match range.kind {
1495                            RangeKind::RangeFrom
1496                            | RangeKind::RangeTo
1497                            | RangeKind::RangeToInclusive => 1,
1498                            RangeKind::Range | RangeKind::RangeInclusive => 2,
1499                        };
1500
1501                        if key != expected_key
1502                            || (range.first.is_some() && max_fields < 2)
1503                            || range.second.is_some()
1504                        {
1505                            range.fallback = true;
1506                        } else if range.first.is_none() {
1507                            // Store the actual key alongside the number so it is
1508                            // replayed correctly if we later fall back to struct form.
1509                            range.first = Some((key, s));
1510                        } else {
1511                            range.second = Some((key, s));
1512                        }
1513
1514                        if !range.fallback {
1515                            return Ok(());
1516                        }
1517                    }
1518                    None => {
1519                        range.fallback = true;
1520                    }
1521                }
1522
1523                // Write the struct opening as `serialize_struct` would have
1524                if range.newtype_variant {
1525                    self.newtype_variant = true;
1526                } else {
1527                    if self.ser.struct_names() {
1528                        self.ser.write_identifier(range.name)?;
1529                    }
1530                    self.ser.output.write_char('(')?;
1531                }
1532                if !self.ser.compact_structs() {
1533                    self.ser.is_empty = Some(false);
1534                    self.ser.start_indent()?;
1535                }
1536
1537                // Replay any buffered numeric fields using their actual stored keys.
1538                let buffered: [Option<(&'static str, crate::value::Number)>; 2] =
1539                    [range.first.take(), range.second.take()];
1540
1541                for (bkey, bval) in buffered.into_iter().flatten() {
1542                    ser::SerializeStruct::serialize_field(self, bkey, &bval)?;
1543                }
1544                // fall through to emit the current field normally
1545            }
1546        }
1547
1548        let mut restore_field = self.ser.pretty.as_mut().and_then(|(config, _)| {
1549            config.path_meta.take().map(|mut field| {
1550                if let Some(fields) = field.fields_mut() {
1551                    config.path_meta = fields.remove(key);
1552                }
1553                field
1554            })
1555        });
1556
1557        if let State::First = self.state {
1558            self.state = State::Rest;
1559        } else {
1560            self.ser.output.write_char(',')?;
1561
1562            if let Some((ref config, ref pretty)) = self.ser.pretty {
1563                if pretty.indent <= config.depth_limit && !config.compact_structs {
1564                    self.ser.output.write_str(&config.new_line)?;
1565                } else {
1566                    self.ser.output.write_str(&config.separator)?;
1567                }
1568            }
1569        }
1570
1571        if !self.ser.compact_structs() {
1572            if let Some((ref config, ref pretty)) = self.ser.pretty {
1573                indent(&mut self.ser.output, config, pretty)?;
1574
1575                if let Some(ref field) = config.path_meta {
1576                    for doc_line in field.doc().lines() {
1577                        self.ser.output.write_str("/// ")?;
1578                        self.ser.output.write_str(doc_line)?;
1579                        self.ser.output.write_str(&config.new_line)?;
1580                        indent(&mut self.ser.output, config, pretty)?;
1581                    }
1582                }
1583            }
1584        }
1585
1586        self.ser.write_identifier(key)?;
1587        self.ser.output.write_char(':')?;
1588
1589        if let Some((ref config, _)) = self.ser.pretty {
1590            self.ser.output.write_str(&config.separator)?;
1591        }
1592
1593        guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
1594
1595        if let Some((ref mut config, _)) = self.ser.pretty {
1596            core::mem::swap(&mut config.path_meta, &mut restore_field);
1597
1598            if let Some(ref mut field) = config.path_meta {
1599                if let Some(fields) = field.fields_mut() {
1600                    if let Some(restore_field) = restore_field {
1601                        fields.insert(key, restore_field);
1602                    }
1603                }
1604            }
1605        };
1606
1607        Ok(())
1608    }
1609
1610    fn end(mut self) -> Result<()> {
1611        if let Some(ref mut range) = self.range {
1612            if !range.fallback {
1613                // All fields were numeric — emit compact syntax.
1614                let sep = match range.kind {
1615                    RangeKind::RangeInclusive | RangeKind::RangeToInclusive => "..=",
1616                    _ => "..",
1617                };
1618
1619                match range.kind {
1620                    RangeKind::RangeFrom => {
1621                        if let Some((_, start)) = range.first.take() {
1622                            start.serialize(&mut *self.ser)?;
1623                        }
1624                        self.ser.output.write_str("..")?;
1625                    }
1626                    RangeKind::RangeTo | RangeKind::RangeToInclusive => {
1627                        self.ser.output.write_str(sep)?;
1628                        if let Some((_, end)) = range.first.take() {
1629                            end.serialize(&mut *self.ser)?;
1630                        }
1631                    }
1632                    RangeKind::Range | RangeKind::RangeInclusive => {
1633                        if let Some((_, start)) = range.first.take() {
1634                            start.serialize(&mut *self.ser)?;
1635                        }
1636                        self.ser.output.write_str(sep)?;
1637                        if let Some((_, end)) = range.second.take() {
1638                            end.serialize(&mut *self.ser)?;
1639                        }
1640                    }
1641                }
1642                return Ok(());
1643            }
1644            // fallback: close the struct normally (end_indent + ')' handled below)
1645        }
1646
1647        if let State::Rest = self.state {
1648            if let Some((ref config, ref pretty)) = self.ser.pretty {
1649                if pretty.indent <= config.depth_limit && !config.compact_structs {
1650                    self.ser.output.write_char(',')?;
1651                    self.ser.output.write_str(&config.new_line)?;
1652                }
1653            }
1654        }
1655
1656        if !self.ser.compact_structs() {
1657            self.ser.end_indent()?;
1658        }
1659
1660        if !self.newtype_variant {
1661            self.ser.output.write_char(')')?;
1662        }
1663
1664        Ok(())
1665    }
1666}
1667
1668impl<'a, W: fmt::Write> ser::SerializeStructVariant for Compound<'a, W> {
1669    type Error = Error;
1670    type Ok = ();
1671
1672    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
1673    where
1674        T: ?Sized + Serialize,
1675    {
1676        ser::SerializeStruct::serialize_field(self, key, value)
1677    }
1678
1679    fn end(self) -> Result<()> {
1680        ser::SerializeStruct::end(self)
1681    }
1682}