Skip to main content

deser_json/
ser.rs

1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::string::ToString;
4use alloc::vec::Vec;
5use core::mem::ManuallyDrop;
6
7use deser_core::__format::IntBuffer;
8use deser_core::ext::{BigInt, Decimal, ExtValue, Number};
9use deser_core::ser::{self, PausableSink, SerializeDriver, Written};
10use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Implicit, ImplicitValue, Serialize};
11
12use crate::Trailing;
13use crate::buf::Buffer;
14use crate::escape::find_escape;
15use crate::pretty::PrettyWriter;
16use crate::scan::skip_to_escape;
17
18/// How the output is indented.
19///
20/// See [`SerializerConfig::indent`] and [`SerializerConfig::pretty`].
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
22#[non_exhaustive]
23pub enum Indent {
24    /// No indentation, the value is written on a single line.
25    #[default]
26    None,
27    /// Every entry on a line of its own, indented by the given number of
28    /// spaces per level.
29    Spaces(usize),
30    /// Every entry on a line of its own, indented by a tab per level.
31    Tab,
32}
33
34/// When maps and sequences are written on a single line in indented
35/// output.
36///
37/// Maps and sequences with the [`Layout::Compact`](deser_core::hints::Layout)
38/// hint are always written on a single line, the ones with
39/// [`Layout::Expanded`](deser_core::hints::Layout) never (unless they are in a
40/// map or sequence on a single line).  See [`SerializerConfig::inline`].
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
42#[non_exhaustive]
43pub enum InlinePolicy {
44    /// Only compact maps and sequences are written on a single line.
45    #[default]
46    Never,
47    /// Maps and sequences which only contain scalars (no maps or
48    /// sequences, not even empty ones) are written on a single line if
49    /// that line is not longer than the given number of characters
50    /// (including the indentation, a tab counts as one character).
51    LeafIfFits(usize),
52}
53
54/// Configures how values are serialized to JSON.
55///
56/// By default the output is as short as possible: no line breaks and no
57/// spaces.  [`pretty`](Self::pretty) writes every entry on a line of its
58/// own:
59///
60/// ```
61/// use std::collections::BTreeMap;
62/// use deser_json::{Indent, SerializerConfig};
63///
64/// let value = BTreeMap::from([("name", vec!["a", "b"])]);
65/// assert_eq!(
66///     deser_json::to_string(&value).unwrap(),
67///     r#"{"name":["a","b"]}"#
68/// );
69///
70/// const PRETTY: SerializerConfig =
71///     SerializerConfig::new().pretty(Indent::Spaces(2));
72/// assert_eq!(
73///     PRETTY.to_string(&value).unwrap(),
74///     "{\n  \"name\": [\n    \"a\",\n    \"b\"\n  ]\n}"
75/// );
76/// ```
77///
78/// In indented output maps and sequences with the
79/// [`Layout::Compact`](deser_core::hints::Layout) hint (see
80/// [`hints`](deser_core::hints)) are written on a single line.  The output never
81/// ends with a line break.
82///
83/// [`to_string`](Self::to_string) works like the
84/// [`to_string`](crate::to_string) function.
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct SerializerConfig {
87    bytes: BytesFormat,
88    indent: Indent,
89    compact: bool,
90    inline: InlinePolicy,
91    trailing: Trailing,
92}
93
94impl Default for SerializerConfig {
95    fn default() -> SerializerConfig {
96        SerializerConfig::new()
97    }
98}
99
100impl SerializerConfig {
101    /// Creates the default configuration.
102    pub const fn new() -> SerializerConfig {
103        SerializerConfig {
104            bytes: BytesFormat::BASE64,
105            indent: Indent::None,
106            compact: true,
107            inline: InlinePolicy::Never,
108            trailing: Trailing::Strict,
109        }
110    }
111
112    /// Sets what follows the values of a stream.
113    ///
114    /// This is the counterpart of
115    /// [`DeserializerConfig::trailing`](crate::DeserializerConfig::trailing)
116    /// for writing more than one value (with a [`Serializer`] or a stream
117    /// writer), it does not affect [`to_string`](Self::to_string):
118    ///
119    /// * [`Trailing::Strict`]: the stream holds a single value, writing a
120    ///   second one fails.  This is the default.
121    /// * [`Trailing::Newline`]: every value is followed by a line break
122    ///   ([JSON Lines](https://jsonlines.org/)).  The values must not be
123    ///   indented.
124    /// * [`Trailing::Stop`]: values are separated by line breaks.
125    ///
126    /// ```
127    /// use deser_json::{Serializer, SerializerConfig, Trailing};
128    ///
129    /// const LINES: SerializerConfig =
130    ///     SerializerConfig::new().trailing(Trailing::Newline);
131    /// let mut serializer = Serializer::with_config(&LINES);
132    /// serializer.serialize(&vec![1, 2]).unwrap();
133    /// serializer.serialize(&vec![3]).unwrap();
134    /// assert_eq!(serializer.finish(), "[1,2]\n[3]\n");
135    /// ```
136    pub const fn trailing(mut self, trailing: Trailing) -> SerializerConfig {
137        self.trailing = trailing;
138        self
139    }
140
141    /// Returns what follows the values of a stream.
142    pub(crate) fn trailing_mode(&self) -> Trailing {
143        self.trailing
144    }
145
146    /// Sets how the output is indented.
147    ///
148    /// By default ([`Indent::None`]) the value is written on a single line.
149    /// Otherwise every entry of a map or sequence is written on a line of
150    /// its own, indented by its depth.  Empty maps and sequences are always
151    /// written as `{}` and `[]`.  This does not change the spaces after
152    /// separators, see [`compact`](Self::compact).  To indent with spaces
153    /// after separators use [`pretty`](Self::pretty).
154    ///
155    /// ```
156    /// use deser_json::{Indent, SerializerConfig};
157    ///
158    /// const TAB: SerializerConfig = SerializerConfig::new().indent(Indent::Tab);
159    /// assert_eq!(TAB.to_string(&vec![1, 2]).unwrap(), "[\n\t1,\n\t2\n]");
160    /// ```
161    pub const fn indent(mut self, indent: Indent) -> SerializerConfig {
162        self.indent = indent;
163        self
164    }
165
166    /// Controls the spaces after separators.
167    ///
168    /// When enabled (which is the default) there are no spaces after `:`
169    /// and `,`.  When disabled a space follows every `:` and every `,`
170    /// that is not followed by a line break:
171    ///
172    /// ```
173    /// use std::collections::BTreeMap;
174    /// use deser_json::SerializerConfig;
175    ///
176    /// let value = BTreeMap::from([("a", vec![1, 2])]);
177    /// const SPACED: SerializerConfig = SerializerConfig::new().compact(false);
178    /// assert_eq!(SPACED.to_string(&value).unwrap(), r#"{"a": [1, 2]}"#);
179    /// ```
180    pub const fn compact(mut self, yes: bool) -> SerializerConfig {
181        self.compact = yes;
182        self
183    }
184
185    /// Sets when maps and sequences are written on a single line in
186    /// indented output.
187    ///
188    /// ```
189    /// use deser::Serialize;
190    /// use deser_json::{Indent, InlinePolicy, SerializerConfig};
191    ///
192    /// #[derive(Serialize)]
193    /// struct Shape {
194    ///     name: &'static str,
195    ///     points: Vec<Vec<i32>>,
196    /// }
197    ///
198    /// let shape = Shape {
199    ///     name: "line",
200    ///     points: vec![vec![0, 0], vec![3, 4]],
201    /// };
202    /// const CONFIG: SerializerConfig = SerializerConfig::new()
203    ///     .pretty(Indent::Spaces(2))
204    ///     .inline(InlinePolicy::LeafIfFits(80));
205    /// assert_eq!(CONFIG.to_string(&shape).unwrap(), r#"{
206    ///   "name": "line",
207    ///   "points": [
208    ///     [0, 0],
209    ///     [3, 4]
210    ///   ]
211    /// }"#);
212    /// ```
213    ///
214    /// This has no effect without [indentation](Self::indent).
215    pub const fn inline(mut self, policy: InlinePolicy) -> SerializerConfig {
216        self.inline = policy;
217        self
218    }
219
220    /// Enables or disables pretty printing.
221    ///
222    /// This sets the [indentation](Self::indent) and writes spaces after
223    /// separators (see [`compact`](Self::compact)) unless the indentation
224    /// is [`Indent::None`], in which case the output is compact again.
225    ///
226    /// ```
227    /// use std::collections::BTreeMap;
228    /// use deser_json::{Indent, SerializerConfig};
229    ///
230    /// let value = BTreeMap::from([("a", 1)]);
231    /// const PRETTY: SerializerConfig =
232    ///     SerializerConfig::new().pretty(Indent::Spaces(4));
233    /// assert_eq!(PRETTY.to_string(&value).unwrap(), "{\n    \"a\": 1\n}");
234    /// const NOT_PRETTY: SerializerConfig = PRETTY.pretty(Indent::None);
235    /// assert_eq!(NOT_PRETTY.to_string(&value).unwrap(), r#"{"a":1}"#);
236    /// ```
237    pub const fn pretty(mut self, indent: Indent) -> SerializerConfig {
238        self.indent = indent;
239        self.compact = matches!(indent, Indent::None);
240        self
241    }
242
243    /// Sets how bytes are represented.
244    ///
245    /// JSON has no bytes, by default they are written as base64 strings
246    /// ([`BytesFormat::BASE64`]).  Values can request a different format
247    /// (see [bytes](deser_core::adapters#bytes)) which takes precedence.  Map keys cannot be
248    /// sequences, bytes in keys are always strings.
249    ///
250    /// ```
251    /// use deser::adapters::Base64UrlNoPad;
252    /// use deser::BytesFormat;
253    /// use deser_json::SerializerConfig;
254    ///
255    /// assert_eq!(deser_json::to_string(&b"\xfb\xff").unwrap(), r#""+/8=""#);
256    /// const URL_SAFE: SerializerConfig = SerializerConfig::new()
257    ///     .bytes(BytesFormat::encoded::<Base64UrlNoPad>());
258    /// assert_eq!(URL_SAFE.to_string(&b"\xfb\xff").unwrap(), r#""-_8""#);
259    /// const SEQ: SerializerConfig =
260    ///     SerializerConfig::new().bytes(BytesFormat::SEQ);
261    /// assert_eq!(SEQ.to_string(&b"\xfb\xff").unwrap(), "[251,255]");
262    /// ```
263    ///
264    /// More encodings (such as hex) are provided by
265    /// [`deser-encoding`](https://docs.rs/deser-encoding).  Bytes in other
266    /// formats than base64 (or sequences) need to be
267    /// deserialized with the same format (see
268    /// [`DeserializerConfig::bytes`](crate::DeserializerConfig::bytes)).
269    pub const fn bytes(mut self, format: BytesFormat) -> SerializerConfig {
270        self.bytes = format;
271        self
272    }
273
274    /// Serializes the given value.
275    pub fn to_string(&self, value: &dyn Serialize) -> Result<String, Error> {
276        self.to_string_with(value, |_| {})
277    }
278
279    /// Serializes the given value with a configured driver.
280    ///
281    /// The callback is invoked with the driver before the serialization
282    /// starts, for instance to add [`Layer`](deser_core::ser::Layer)s.
283    ///
284    /// ```
285    /// use deser::ser::{Layer, Next};
286    /// use deser::{Atom, Error, Event};
287    /// use deser_json::SerializerConfig;
288    ///
289    /// /// Writes all numbers as strings.
290    /// struct NumbersAsStrings;
291    ///
292    /// impl Layer for NumbersAsStrings {
293    ///     fn event(
294    ///         &mut self,
295    ///         event: Event<'_>,
296    ///         next: &mut Next<'_>,
297    ///     ) -> Result<(), Error> {
298    ///         match event {
299    ///             Event::Atom(Atom::U64(value)) => {
300    ///                 next.emit(value.to_string().into())
301    ///             }
302    ///             event => next.emit(event),
303    ///         }
304    ///     }
305    /// }
306    ///
307    /// let json = SerializerConfig::new()
308    ///     .to_string_with(&vec![1u64, 2], |driver| {
309    ///         driver.push_layer(NumbersAsStrings)
310    ///     })
311    ///     .unwrap();
312    /// assert_eq!(json, r#"["1","2"]"#);
313    /// ```
314    pub fn to_string_with<F>(&self, value: &dyn Serialize, setup: F) -> Result<String, Error>
315    where
316        F: FnOnce(&mut SerializeDriver<'_>),
317    {
318        let mut driver = SerializeDriver::new(value);
319        setup(&mut driver);
320        self.serialize_driver(&mut driver)
321    }
322
323    /// Serializes the value of a driver.
324    pub(crate) fn serialize_driver(
325        &self,
326        driver: &mut SerializeDriver<'_>,
327    ) -> Result<String, Error> {
328        let mut writer = self.value_writer(Buffer::with_capacity(128));
329        writer.drive(driver, usize::MAX)?;
330        Ok(writer.finish())
331    }
332
333    /// Creates the writer for a value which writes into the buffer.
334    pub(crate) fn value_writer(&self, out: Buffer) -> ValueWriter {
335        let ser = Output {
336            out,
337            bytes: self.bytes,
338        };
339        if self.indent == Indent::None && self.compact {
340            ValueWriter::Compact(Writer {
341                ser,
342                stack: Vec::new(),
343                container: Container::Top,
344                first: true,
345                is_key: false,
346                limit: usize::MAX,
347            })
348        } else {
349            let inline_width = match self.inline {
350                InlinePolicy::Never => None,
351                InlinePolicy::LeafIfFits(width) => Some(width),
352            };
353            ValueWriter::Pretty(PrettyWriter::new(
354                ser,
355                self.indent,
356                self.compact,
357                inline_width,
358            ))
359        }
360    }
361}
362
363/// Writes the events of a value.
364pub(crate) enum ValueWriter {
365    /// Compact output (no indentation, no spaces).
366    Compact(Writer),
367    /// Everything else.
368    Pretty(PrettyWriter),
369}
370
371impl ValueWriter {
372    /// Writes the events of the driver.
373    ///
374    /// Returns `false` if the driver was paused as the output holds at
375    /// least `limit` bytes (see `take_output`).  With a limit of
376    /// `usize::MAX` the value is written at once.
377    pub(crate) fn drive(
378        &mut self,
379        driver: &mut SerializeDriver<'_>,
380        limit: usize,
381    ) -> Result<bool, Error> {
382        match self {
383            ValueWriter::Compact(writer) if limit == usize::MAX => {
384                driver.drive_sink(writer).map(|()| true)
385            }
386            ValueWriter::Compact(writer) => {
387                writer.limit = limit;
388                driver.drive_until(writer)
389            }
390            ValueWriter::Pretty(writer) if limit == usize::MAX => driver
391                .drive(|event, state| writer.event(event, state))
392                .map(|()| true),
393            ValueWriter::Pretty(writer) => {
394                writer.limit = limit;
395                driver.drive_until(writer)
396            }
397        }
398    }
399
400    /// Returns the output buffer.
401    pub(crate) fn output(&mut self) -> &mut Buffer {
402        match self {
403            ValueWriter::Compact(writer) => &mut writer.ser.out,
404            ValueWriter::Pretty(writer) => writer.output(),
405        }
406    }
407
408    /// Takes the output written so far (which is final after `drive`
409    /// returned), the writer continues with an empty output.
410    pub(crate) fn take_output(&mut self) -> Vec<u8> {
411        match self {
412            ValueWriter::Compact(writer) => writer.ser.out.take(),
413            ValueWriter::Pretty(writer) => writer.take_output(),
414        }
415    }
416
417    /// Returns the output.
418    pub(crate) fn finish(self) -> String {
419        match self {
420            ValueWriter::Compact(writer) => writer.ser.out.into_string(),
421            ValueWriter::Pretty(writer) => writer.finish(),
422        }
423    }
424}
425
426/// Serializes values into JSON.
427///
428/// Every call to [`serialize`](Self::serialize) writes a value.  What
429/// follows the values depends on [`SerializerConfig::trailing`]: by default
430/// only a single value can be written, with [`Trailing::Newline`] every
431/// value is followed by a line break ([JSON Lines](https://jsonlines.org/)).
432///
433/// ```
434/// use deser_json::{Serializer, SerializerConfig, Trailing};
435///
436/// const LINES: SerializerConfig =
437///     SerializerConfig::new().trailing(Trailing::Newline);
438/// let mut serializer = Serializer::with_config(&LINES);
439/// serializer.serialize(&vec![1, 2]).unwrap();
440/// serializer.serialize(&"x").unwrap();
441/// assert_eq!(serializer.finish(), "[1,2]\n\"x\"\n");
442/// ```
443///
444/// The serializer is also the stream serializer of JSON (see
445/// [`StreamSerializer`](ser::StreamSerializer)): the output can be taken
446/// while values are written, and large values can be written in parts.
447/// To write to a [`Write`](std::io::Write) use
448/// [`SerializerConfig::writer`]:
449///
450/// ```
451/// # #[cfg(feature = "io")] {
452/// use deser_json::SerializerConfig;
453///
454/// let mut writer = SerializerConfig::new().writer(Vec::new());
455/// writer.set_buffer_limit(4);
456/// writer.write(&vec!["a", "b", "c"]).unwrap();
457/// assert_eq!(writer.into_inner(), br#"["a","b","c"]"#);
458/// # }
459/// ```
460pub struct Serializer {
461    config: SerializerConfig,
462    // only holds the output of value writers and line breaks, which is
463    // valid UTF-8
464    out: Vec<u8>,
465    written: usize,
466    // the value that is written in parts
467    value: Option<Box<ValueWriter>>,
468    // a value was started with `drive_partial` and is not complete
469    in_progress: bool,
470}
471
472impl Default for Serializer {
473    fn default() -> Serializer {
474        Serializer::new()
475    }
476}
477
478impl Clone for Serializer {
479    /// Clones the serializer.
480    ///
481    /// The clone of a serializer that writes a value in parts cannot write
482    /// more values (see
483    /// [`StreamSerializer::in_progress`](ser::StreamSerializer::in_progress)).
484    fn clone(&self) -> Serializer {
485        Serializer {
486            config: self.config.clone(),
487            out: self.out.clone(),
488            written: self.written,
489            value: None,
490            in_progress: self.in_progress,
491        }
492    }
493}
494
495impl core::fmt::Debug for Serializer {
496    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
497        f.debug_struct("Serializer")
498            .field("config", &self.config)
499            .field("output", &self.as_str())
500            .field("written", &self.written)
501            .field("in_progress", &self.in_progress)
502            .finish()
503    }
504}
505
506impl Serializer {
507    /// Creates a serializer.
508    pub fn new() -> Serializer {
509        Serializer::with_config(&SerializerConfig::new())
510    }
511
512    /// Creates a serializer with the given configuration.
513    pub fn with_config(config: &SerializerConfig) -> Serializer {
514        Serializer::with_written(config, 0)
515    }
516
517    /// Creates a serializer for a stream that continues after the given
518    /// number of values.
519    ///
520    /// This is useful to append to a stream that was written before (see
521    /// [`SerializerConfig::trailing`] for what separates the values).
522    pub fn with_written(config: &SerializerConfig, written: usize) -> Serializer {
523        Serializer {
524            config: config.clone(),
525            out: Vec::new(),
526            written,
527            value: None,
528            in_progress: false,
529        }
530    }
531
532    /// Returns the configuration.
533    pub fn config(&self) -> &SerializerConfig {
534        &self.config
535    }
536
537    /// Returns the number of values that were written.
538    pub fn written(&self) -> usize {
539        self.written
540    }
541
542    /// Serializes a value.
543    ///
544    /// If the value fails to serialize, nothing is written.
545    pub fn serialize(&mut self, value: &dyn Serialize) -> Result<(), Error> {
546        ser::Serializer::serialize(self, value)
547    }
548
549    /// Serializes a value with a configured driver.
550    ///
551    /// The callback is invoked with the driver before the value is
552    /// serialized, for instance to add [`Layer`](deser_core::ser::Layer)s.
553    pub fn serialize_with<F>(&mut self, value: &dyn Serialize, setup: F) -> Result<(), Error>
554    where
555        F: FnOnce(&mut SerializeDriver<'_>),
556    {
557        ser::Serializer::serialize_with(self, value, setup)
558    }
559
560    /// Returns the output written so far (that was not cleared).
561    pub fn as_str(&self) -> &str {
562        // SAFETY: the output is valid UTF-8, see `out`
563        unsafe { core::str::from_utf8_unchecked(&self.out) }
564    }
565
566    /// Returns the output.
567    pub fn finish(self) -> String {
568        // SAFETY: the output is valid UTF-8, see `out`
569        unsafe { String::from_utf8_unchecked(self.out) }
570    }
571
572    /// Starts a value: writes what separates it from the previous value.
573    fn start_value(&mut self) -> Result<(), Error> {
574        if self.in_progress {
575            return Err(Error::in_progress());
576        }
577        match self.config.trailing_mode() {
578            Trailing::Strict if self.written > 0 => Err(Error::new(
579                ErrorKind::Unexpected,
580                "with Trailing::Strict only a single value can be written",
581            )),
582            Trailing::Stop if self.written > 0 => {
583                self.out.push(b'\n');
584                Ok(())
585            }
586            _ => Ok(()),
587        }
588    }
589
590    /// Completes a value.
591    fn finish_value(&mut self) {
592        if self.config.trailing_mode() == Trailing::Newline {
593            self.out.push(b'\n');
594        }
595        self.written += 1;
596        self.in_progress = false;
597    }
598}
599
600impl ser::Serializer for Serializer {
601    fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
602        // only `drive_partial` continues a value
603        if self.in_progress {
604            return Err(Error::in_progress());
605        }
606        ser::StreamSerializer::drive_partial(self, driver, usize::MAX).map(|_| ())
607    }
608}
609
610impl ser::StreamSerializer for Serializer {
611    fn output(&self) -> &[u8] {
612        &self.out
613    }
614
615    fn clear_output(&mut self) {
616        self.out.clear();
617    }
618
619    fn supports_partial(&self) -> bool {
620        true
621    }
622
623    fn drive_partial(
624        &mut self,
625        driver: &mut SerializeDriver<'_>,
626        limit: usize,
627    ) -> Result<Written, Error> {
628        let rollback = self.out.len();
629        let (mut local, adopt) = match self.value.take() {
630            // the writer writes into the output directly if it's empty,
631            // otherwise its output is appended
632            Some(mut writer) => {
633                let adopt = self.out.is_empty();
634                if adopt {
635                    *writer.output() = Buffer::from_vec(core::mem::take(&mut self.out));
636                }
637                (writer, adopt)
638            }
639            None => {
640                self.start_value()?;
641                // a writer that completes the value at once is not boxed
642                let out = Buffer::from_vec(core::mem::take(&mut self.out));
643                let writer = self.config.value_writer(out);
644                if limit == usize::MAX {
645                    return self.drive_whole(writer, driver, rollback);
646                }
647                (Box::new(writer), true)
648            }
649        };
650        let rv = local.drive(driver, limit);
651        match rv {
652            Ok(done) => {
653                let output = local.take_output();
654                if adopt {
655                    self.out = output;
656                } else {
657                    self.out.extend_from_slice(&output);
658                }
659                if done {
660                    self.finish_value();
661                    Ok(Written::Done)
662                } else {
663                    self.value = Some(local);
664                    self.in_progress = true;
665                    Ok(Written::Partial)
666                }
667            }
668            Err(err) => {
669                // the value is abandoned, what was written of it is
670                // discarded.  If parts of it were taken the stream stays
671                // broken (`in_progress`).
672                if adopt {
673                    self.out = local.output().take();
674                    self.out.truncate(rollback);
675                }
676                Err(err)
677            }
678        }
679    }
680
681    fn in_progress(&self) -> bool {
682        self.in_progress
683    }
684}
685
686impl Serializer {
687    /// Writes a value at once (see `drive_partial`).
688    fn drive_whole(
689        &mut self,
690        mut writer: ValueWriter,
691        driver: &mut SerializeDriver<'_>,
692        rollback: usize,
693    ) -> Result<Written, Error> {
694        let rv = writer.drive(driver, usize::MAX);
695        self.out = writer.output().take();
696        match rv {
697            Ok(_) => {
698                self.finish_value();
699                Ok(Written::Done)
700            }
701            Err(err) => {
702                self.out.truncate(rollback);
703                Err(err)
704            }
705        }
706    }
707}
708
709#[cfg(feature = "io")]
710impl SerializerConfig {
711    /// Creates a writer of a stream of values (see
712    /// [`deser::io::Writer`](deser_core::io::Writer)).
713    ///
714    /// What follows the values depends on [`trailing`](Self::trailing).
715    /// The output of large values is written in parts while they are
716    /// serialized.
717    ///
718    /// ```
719    /// use deser_json::{SerializerConfig, Trailing};
720    ///
721    /// const LINES: SerializerConfig =
722    ///     SerializerConfig::new().trailing(Trailing::Newline);
723    /// let mut writer = LINES.writer(Vec::new());
724    /// writer.write(&1).unwrap();
725    /// writer.write(&"x").unwrap();
726    /// assert_eq!(writer.into_inner(), b"1\n\"x\"\n");
727    /// ```
728    pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
729        deser_core::io::Writer::new(writer, Serializer::with_config(self))
730    }
731
732    /// Serializes a value to a writer.
733    ///
734    /// See [`to_writer`](crate::to_writer).
735    pub fn to_writer<W: std::io::Write>(
736        &self,
737        writer: W,
738        value: &dyn Serialize,
739    ) -> Result<(), Error> {
740        self.writer(writer).write(value)
741    }
742}
743
744/// Serializes a value to a writer.
745///
746/// The output of large values is written in parts while they are
747/// serialized (see [`deser::io`](deser_core::io)), the writer does not
748/// need to be buffered.
749///
750/// ```
751/// let mut out = Vec::new();
752/// deser_json::to_writer(&mut out, &vec![1, 2, 3]).unwrap();
753/// assert_eq!(out, b"[1,2,3]");
754/// ```
755#[cfg(feature = "io")]
756pub fn to_writer<W: std::io::Write>(writer: W, value: &dyn Serialize) -> Result<(), Error> {
757    SerializerConfig::new().to_writer(writer, value)
758}
759
760/// The output of the serializer.
761pub(crate) struct Output {
762    pub(crate) out: Buffer,
763    bytes: BytesFormat,
764}
765
766#[derive(Clone, Copy, PartialEq, Eq)]
767enum Container {
768    Top,
769    Seq,
770    Map,
771}
772
773/// Holds the state of the serializer while writing.
774pub(crate) struct Writer {
775    ser: Output,
776    // the state of the current container is held here, the state of the
777    // outer containers is saved on the stack.
778    stack: Vec<Container>,
779    container: Container,
780    first: bool,
781    is_key: bool,
782    // the output is passed on once it's this long (see `PausableSink`)
783    limit: usize,
784}
785
786impl ser::EventSink for Writer {
787    #[inline(always)]
788    fn event(&mut self, event: Event, _state: &mut deser_core::State) -> Result<(), Error> {
789        Writer::event(self, event)
790    }
791}
792
793impl PausableSink for Writer {
794    #[inline(always)]
795    fn event(
796        &mut self,
797        event: Event<'_>,
798        _value: &dyn Serialize,
799        _state: &mut deser_core::State,
800    ) -> Result<(), Error> {
801        Writer::event(self, event)
802    }
803
804    #[inline(always)]
805    fn pause(&mut self) -> bool {
806        self.ser.out.len() >= self.limit
807    }
808}
809
810impl Writer {
811    #[inline(always)]
812    fn event(&mut self, event: Event) -> Result<(), Error> {
813        match event {
814            Event::Atom(atom) => {
815                if self.is_key {
816                    self.ser.write_key_atom(atom, self.first)?;
817                    self.is_key = false;
818                } else {
819                    match self.container {
820                        Container::Seq => {
821                            if !self.first {
822                                self.ser.write_char(',');
823                            }
824                        }
825                        Container::Map => self.is_key = true,
826                        Container::Top => {}
827                    }
828                    self.ser.write_atom(atom)?;
829                }
830                self.first = false;
831                Ok(())
832            }
833            Event::MapStart(_) => self.start(true),
834            Event::SeqStart(_) => self.start(false),
835            Event::MapEnd => self.end(true),
836            Event::SeqEnd => self.end(false),
837        }
838    }
839
840    #[inline]
841    fn start(&mut self, is_map: bool) -> Result<(), Error> {
842        if self.is_key {
843            return Err(Error::new(
844                ErrorKind::UnsupportedType,
845                "JSON does not support this value for map keys",
846            ));
847        }
848        if self.container == Container::Seq && !self.first {
849            self.ser.write_char(',');
850        }
851        self.stack.push(self.container);
852        self.first = true;
853        if is_map {
854            self.container = Container::Map;
855            self.is_key = true;
856            self.ser.write_char('{');
857        } else {
858            self.container = Container::Seq;
859            self.ser.write_char('[');
860        }
861        Ok(())
862    }
863
864    #[inline]
865    fn end(&mut self, is_map: bool) -> Result<(), Error> {
866        if is_map {
867            if self.container != Container::Map || !self.is_key {
868                return Err(Error::new(ErrorKind::Unexpected, "unexpected map end"));
869            }
870            self.ser.write_char('}');
871        } else {
872            if self.container != Container::Seq {
873                return Err(Error::new(ErrorKind::Unexpected, "unexpected array end"));
874            }
875            self.ser.write_char(']');
876        }
877        self.container = self.stack.pop().unwrap_or(Container::Top);
878        // a container is never a key, so after it the next item in a map is
879        // a key again.
880        self.first = false;
881        self.is_key = self.container == Container::Map;
882        Ok(())
883    }
884}
885
886impl Output {
887    /// Writes an atom in key position including separator and colon.
888    #[inline(always)]
889    fn write_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
890        // borrowed strings do not need to be dropped, the atom is only
891        // dropped for the other values.
892        let atom = ManuallyDrop::new(atom);
893        match *atom {
894            // fast path for the common case of string keys
895            Atom::Str(ref val) | Atom::Lexical(ref val) if val.is_borrowed() => {
896                self.write_key(val, first);
897                Ok(())
898            }
899            _ => self.write_other_key_atom(ManuallyDrop::into_inner(atom), first),
900        }
901    }
902
903    #[inline(never)]
904    fn write_other_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
905        if !first {
906            self.write_char(',');
907        }
908        self.write_key_text(atom)?;
909        self.write_char(':');
910        Ok(())
911    }
912
913    /// Writes an atom as map key without separator and colon.
914    pub(crate) fn write_key_text(&mut self, atom: Atom) -> Result<(), Error> {
915        match atom {
916            Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
917            Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
918            Atom::U64(val) => {
919                self.write_char('"');
920                self.write_u64(val);
921                self.write_char('"');
922            }
923            Atom::I64(val) => {
924                self.write_char('"');
925                self.write_i64(val);
926                self.write_char('"');
927            }
928            Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
929            Atom::Ext(ref ext) => self.write_ext_key(ext)?,
930            Atom::Bytes(ref val) => self.write_bytes_str(val, val.fallback),
931            Atom::Implicit(ref val) => match json_literal(val) {
932                Some(text) if val.value() != ImplicitValue::Null => self.write_escaped_str(text),
933                _ => return self.write_key_text(val.value().to_atom()),
934            },
935            _ => {
936                return Err(Error::new(
937                    ErrorKind::UnsupportedType,
938                    "JSON does not support this value for map keys",
939                ));
940            }
941        }
942        Ok(())
943    }
944
945    /// Writes an atom in value position.
946    #[inline(always)]
947    pub(crate) fn write_atom(&mut self, atom: Atom) -> Result<(), Error> {
948        // borrowed strings and scalars do not need to be dropped, the atom
949        // is only dropped for the other values.
950        let atom = ManuallyDrop::new(atom);
951        match *atom {
952            Atom::Null => self.write_str("null"),
953            Atom::Bool(true) => self.write_str("true"),
954            Atom::Bool(false) => self.write_str("false"),
955            Atom::Str(ref val) if val.is_borrowed() => self.write_escaped_str(val),
956            Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
957            Atom::U64(val) => self.write_u64(val),
958            Atom::I64(val) => self.write_i64(val),
959            Atom::F64(val) => self.write_float(val),
960            Atom::F32(val) => self.write_float(val),
961            _ => return self.write_other_atom(ManuallyDrop::into_inner(atom)),
962        }
963        Ok(())
964    }
965
966    #[inline(never)]
967    fn write_other_atom(&mut self, atom: Atom) -> Result<(), Error> {
968        match atom {
969            Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
970            Atom::Ext(ref ext) => self.write_ext_value(ext)?,
971            Atom::Bytes(ref val) => {
972                self.write_bytes(val, val.fallback.copied().unwrap_or(self.bytes))
973            }
974            // values whose type was inferred from text keep their text if
975            // it's the same value in JSON, otherwise they are written as
976            // their value
977            Atom::Implicit(ref val) => match json_literal(val) {
978                Some(text) => self.write_str(text),
979                None => return self.write_atom(val.value().to_atom()),
980            },
981            _ => return Err(Error::new(ErrorKind::UnsupportedType, "unknown atom")),
982        }
983        Ok(())
984    }
985
986    /// Writes bytes in the given format.
987    fn write_bytes(&mut self, bytes: &[u8], format: BytesFormat) {
988        match format.encode(bytes) {
989            Some(encoded) => self.write_escaped_str(&encoded),
990            None => {
991                self.write_char('[');
992                for (idx, &byte) in bytes.iter().enumerate() {
993                    if idx > 0 {
994                        self.write_char(',');
995                    }
996                    self.write_u64(byte.into());
997                }
998                self.write_char(']');
999            }
1000        }
1001    }
1002
1003    /// Writes bytes as string, for instance as map key.
1004    ///
1005    /// Bytes that would be sequences are base64.
1006    fn write_bytes_str(&mut self, bytes: &[u8], fallback: Option<&BytesFormat>) {
1007        let format = fallback.copied().unwrap_or(self.bytes);
1008        let encoded = format
1009            .encode(bytes)
1010            .or_else(|| BytesFormat::BASE64.encode(bytes))
1011            .unwrap_or_default();
1012        self.write_escaped_str(&encoded);
1013    }
1014
1015    #[inline(always)]
1016    pub(crate) fn write_str(&mut self, s: &str) {
1017        self.out.push_str(s);
1018    }
1019
1020    #[inline(always)]
1021    pub(crate) fn write_char(&mut self, c: char) {
1022        debug_assert!(c.is_ascii());
1023        self.out.push(c as u8);
1024    }
1025
1026    /// Writes a map key including the separator and the colon.
1027    #[inline]
1028    fn write_key(&mut self, key: &str, first: bool) {
1029        if find_escape(key.as_bytes()) != key.len() {
1030            if !first {
1031                self.write_char(',');
1032            }
1033            self.write_escaped_str_slow(key);
1034            self.write_char(':');
1035            return;
1036        }
1037        self.out.reserve(key.len() + 4);
1038        // SAFETY: the capacity was reserved above
1039        unsafe {
1040            if !first {
1041                self.out.push_unchecked(b',');
1042            }
1043            self.out.push_unchecked(b'"');
1044            self.out.push_str_unchecked(key);
1045            self.out.push_unchecked(b'"');
1046            self.out.push_unchecked(b':');
1047        }
1048    }
1049
1050    /// Writes a float with the shortest text that reads back as the same
1051    /// value of its type (`f32` or `f64`).
1052    #[inline]
1053    fn write_float<F: Float>(&mut self, val: F) {
1054        if val.is_finite() {
1055            #[cfg(feature = "speedups")]
1056            {
1057                self.write_str(zmij::Buffer::new().format_finite(val))
1058            }
1059            #[cfg(not(feature = "speedups"))]
1060            {
1061                self.write_str(&deser_core::__format::format_finite(val))
1062            }
1063        } else {
1064            self.write_str("null")
1065        }
1066    }
1067
1068    /// Writes an extension value as map key.
1069    ///
1070    /// Extension values that JSON does not natively support are written in
1071    /// their fallback representation.
1072    #[cold]
1073    fn write_ext_key(&mut self, ext: &ExtValue) -> Result<(), Error> {
1074        if ext.is::<u128>() || ext.is::<i128>() {
1075            self.write_char('"');
1076            self.write_ext_value(ext)?;
1077            self.write_char('"');
1078            return Ok(());
1079        }
1080        match ext.fallback() {
1081            Atom::Str(val) | Atom::Lexical(val) => self.write_escaped_str(&val),
1082            Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1083            Atom::U64(val) => {
1084                self.write_char('"');
1085                self.write_u64(val);
1086                self.write_char('"');
1087            }
1088            Atom::I64(val) => {
1089                self.write_char('"');
1090                self.write_i64(val);
1091                self.write_char('"');
1092            }
1093            Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
1094            _ => {
1095                return Err(Error::new(
1096                    ErrorKind::UnsupportedType,
1097                    "JSON does not support this value for map keys",
1098                ));
1099            }
1100        }
1101        Ok(())
1102    }
1103
1104    /// Writes an extension value.
1105    ///
1106    /// Extension values that JSON does not natively support are written in
1107    /// their fallback representation.
1108    #[cold]
1109    fn write_ext_value(&mut self, ext: &ExtValue) -> Result<(), Error> {
1110        // JSON numbers have arbitrary precision, so wide integers and
1111        // decimals can be written natively.
1112        if let Some(&val) = ext.downcast_ref::<u128>() {
1113            self.write_int(val);
1114            return Ok(());
1115        } else if let Some(&val) = ext.downcast_ref::<i128>() {
1116            self.write_int(val);
1117            return Ok(());
1118        } else if let Some(val) = ext.downcast_ref::<BigInt>() {
1119            self.write_str(&val.to_string());
1120            return Ok(());
1121        } else if let Some(val) = ext.downcast_ref::<Decimal>() {
1122            // decimals use the syntax of JSON numbers
1123            self.write_str(val.as_str());
1124            return Ok(());
1125        } else if let Some(val) = ext.downcast_value_ref::<Number>() {
1126            // numbers keep their text, so they roundtrip exactly
1127            self.write_str(val.as_str());
1128            return Ok(());
1129        }
1130        match ext.fallback() {
1131            Atom::Null => self.write_str("null"),
1132            Atom::Bool(val) => self.write_str(if val { "true" } else { "false" }),
1133            Atom::Str(val) | Atom::Lexical(val) => self.write_escaped_str(&val),
1134            Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1135            Atom::U64(val) => self.write_u64(val),
1136            Atom::I64(val) => self.write_i64(val),
1137            Atom::F64(val) => self.write_float(val),
1138            Atom::F32(val) => self.write_float(val),
1139            // like in TOML the fallbacks of extension values are never
1140            // sequences
1141            Atom::Bytes(val) => self.write_bytes_str(&val, val.fallback),
1142            _ => {
1143                return Err(Error::new(
1144                    ErrorKind::UnsupportedType,
1145                    "JSON does not support this value",
1146                ));
1147            }
1148        }
1149        Ok(())
1150    }
1151
1152    fn write_int<I: core::fmt::Display>(&mut self, val: I) {
1153        self.write_str(&val.to_string())
1154    }
1155
1156    #[inline]
1157    fn write_u64(&mut self, val: u64) {
1158        self.write_str(IntBuffer::new().format_u64(val))
1159    }
1160
1161    #[inline]
1162    fn write_i64(&mut self, val: i64) {
1163        self.write_str(IntBuffer::new().format_i64(val))
1164    }
1165
1166    #[inline]
1167    fn write_escaped_str(&mut self, value: &str) {
1168        if find_escape(value.as_bytes()) != value.len() {
1169            return self.write_escaped_str_slow(value);
1170        }
1171        self.out.reserve(value.len() + 2);
1172        // SAFETY: the capacity was reserved above
1173        unsafe {
1174            self.out.push_unchecked(b'"');
1175            self.out.push_str_unchecked(value);
1176            self.out.push_unchecked(b'"');
1177        }
1178    }
1179
1180    #[inline(never)]
1181    fn write_escaped_str_slow(&mut self, value: &str) {
1182        self.write_char('"');
1183
1184        let bytes = value.as_bytes();
1185        let mut start = 0;
1186
1187        loop {
1188            let next = skip_to_escape(bytes, start);
1189            if start < next {
1190                self.write_str(&value[start..next]);
1191            }
1192            if next == bytes.len() {
1193                break;
1194            }
1195
1196            let byte = bytes[next];
1197            match ESCAPE[byte as usize] {
1198                self::BB => self.write_str("\\b"),
1199                self::TT => self.write_str("\\t"),
1200                self::NN => self.write_str("\\n"),
1201                self::FF => self.write_str("\\f"),
1202                self::RR => self.write_str("\\r"),
1203                self::QU => self.write_str("\\\""),
1204                self::BS => self.write_str("\\\\"),
1205                self::U => {
1206                    static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
1207                    self.write_str("\\u00");
1208                    self.write_char(HEX_DIGITS[(byte >> 4) as usize] as char);
1209                    self.write_char(HEX_DIGITS[(byte & 0xF) as usize] as char);
1210                }
1211                _ => unreachable!(),
1212            }
1213
1214            start = next + 1;
1215        }
1216
1217        self.write_char('"');
1218    }
1219}
1220
1221const BB: u8 = b'b'; // \x08
1222const TT: u8 = b't'; // \x09
1223const NN: u8 = b'n'; // \x0A
1224const FF: u8 = b'f'; // \x0C
1225const RR: u8 = b'r'; // \x0D
1226const QU: u8 = b'"'; // \x22
1227const BS: u8 = b'\\'; // \x5C
1228const U: u8 = b'u'; // \x00...\x1F except the ones above
1229
1230// Lookup table of escape sequences. A value of b'x' at index i means that byte
1231// i is escaped as "\x" in JSON. A value of 0 means that byte i is not escaped.
1232#[rustfmt::skip]
1233static ESCAPE: [u8; 256] = [
1234    //  1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
1235    U,  U,  U,  U,  U,  U,  U,  U, BB, TT, NN,  U, FF, RR,  U,  U, // 0
1236    U,  U,  U,  U,  U,  U,  U,  U,  U,  U,  U,  U,  U,  U,  U,  U, // 1
1237    0,  0, QU,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 2
1238    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 3
1239    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 4
1240    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, BS,  0,  0,  0, // 5
1241    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 6
1242    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 7
1243    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 8
1244    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 9
1245    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // A
1246    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // B
1247    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // C
1248    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // D
1249    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // E
1250    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // F
1251];
1252
1253/// The floats that are written (`f32` and `f64`).
1254#[cfg(feature = "speedups")]
1255trait Float: zmij::Float + deser_core::__format::Float {}
1256
1257#[cfg(feature = "speedups")]
1258impl<F: zmij::Float + deser_core::__format::Float> Float for F {}
1259
1260/// The floats that are written (`f32` and `f64`).
1261#[cfg(not(feature = "speedups"))]
1262trait Float: deser_core::__format::Float {}
1263
1264#[cfg(not(feature = "speedups"))]
1265impl<F: deser_core::__format::Float> Float for F {}
1266
1267/// Serializes a value to JSON.
1268///
1269/// This uses the default [`SerializerConfig`].
1270pub fn to_string(value: &dyn Serialize) -> Result<String, Error> {
1271    SerializerConfig::new().to_string(value)
1272}
1273
1274/// Returns the text of an implicit value if it's a JSON literal for the
1275/// same value.
1276///
1277/// This keeps the text of numbers like `1.10` which would otherwise be
1278/// written as `1.1`.  Text that is not JSON (like `0x1F` or `~`) is not.
1279fn json_literal<'a>(value: &'a Implicit) -> Option<&'a str> {
1280    let text = value.text().as_str();
1281    let same = match value.value() {
1282        ImplicitValue::Null => text == "null",
1283        ImplicitValue::Bool(value) => text == if value { "true" } else { "false" },
1284        ImplicitValue::U64(value) => is_json_int(text) && text.parse::<u64>() == Ok(value),
1285        ImplicitValue::I64(value) => is_json_int(text) && text.parse::<i64>() == Ok(value),
1286        ImplicitValue::F64(value) => {
1287            value.is_finite()
1288                && Number::parse(text)
1289                    .is_ok_and(|x| !x.is_integer() && x.value().to_bits() == value.to_bits())
1290        }
1291        _ => false,
1292    };
1293    same.then_some(text)
1294}
1295
1296/// Checks the syntax of JSON integers (an optional minus and digits
1297/// without leading zeros).
1298fn is_json_int(text: &str) -> bool {
1299    let digits = text.strip_prefix('-').unwrap_or(text).as_bytes();
1300    match digits {
1301        [b'0'] => true,
1302        [b'1'..=b'9', rest @ ..] => rest.iter().all(u8::is_ascii_digit),
1303        _ => false,
1304    }
1305}