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