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}