json_canon/
ser.rs

1use core::num::FpCategory;
2use serde::Serialize;
3use serde_json::{
4    ser::{CharEscape, CompactFormatter, Formatter},
5    Result, Serializer,
6};
7
8use std::io::{self, Error, ErrorKind, Write};
9
10use crate::object::ObjectStack;
11
12/// Serialize the given value as a String of JSON.
13///
14/// Serialization is performed as specified in [RFC 8785](https://tools.ietf.org/html/rfc8785).
15///
16/// # Errors
17///
18/// Serialization can fail if `T`'s implementation of `Serialize` fails.
19#[inline]
20pub fn to_string<T>(value: &T) -> Result<String>
21where
22    T: Serialize + ?Sized,
23{
24    let data: Vec<u8> = to_vec(value)?;
25
26    let data: String = unsafe { String::from_utf8_unchecked(data) };
27
28    Ok(data)
29}
30
31/// Serialize the given value as a JSON byte vector.
32///
33/// Serialization is performed as specified in [RFC 8785](https://tools.ietf.org/html/rfc8785).
34///
35/// # Errors
36///
37/// Serialization can fail if `T`'s implementation of `Serialize` fails.
38#[inline]
39pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
40where
41    T: Serialize + ?Sized,
42{
43    let mut data: Vec<u8> = Vec::with_capacity(128);
44
45    to_writer(&mut data, value)?;
46
47    Ok(data)
48}
49
50/// Serialize the given value as JSON into the IO stream.
51///
52/// Serialization is performed as specified in [RFC 8785](https://tools.ietf.org/html/rfc8785).
53///
54/// # Errors
55///
56/// Serialization can fail if `T`'s implementation of `Serialize` fails.
57#[inline]
58pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
59where
60    W: Write,
61    T: Serialize + ?Sized,
62{
63    value.serialize(&mut Serializer::with_formatter(
64        writer,
65        CanonicalFormatter::new(),
66    ))
67}
68
69static MAX_SAFE_INTEGER_U64: u64 = 9_007_199_254_740_991;
70static MAX_SAFE_INTEGER_I64: i64 = 9_007_199_254_740_991;
71static MAX_SAFE_INTEGER_U128: u128 = 9_007_199_254_740_991;
72static MAX_SAFE_INTEGER_I128: i128 = 9_007_199_254_740_991;
73
74#[derive(Clone, Debug)]
75#[repr(transparent)]
76pub struct CanonicalFormatter {
77    stack: ObjectStack,
78}
79
80impl CanonicalFormatter {
81    pub fn new() -> Self {
82        Self {
83            stack: ObjectStack::new(),
84        }
85    }
86}
87
88impl Formatter for CanonicalFormatter {
89    /// Writes a `null` value to the specified writer.
90    #[inline]
91    fn write_null<W>(&mut self, writer: &mut W) -> io::Result<()>
92    where
93        W: Write + ?Sized,
94    {
95        let mut writer = self.stack.scope(writer)?;
96        writer.write_all(b"null")?;
97        Ok(())
98    }
99
100    /// Writes a `true` or `false` value to the specified writer.
101    #[inline]
102    fn write_bool<W>(&mut self, writer: &mut W, value: bool) -> io::Result<()>
103    where
104        W: Write + ?Sized,
105    {
106        let mut writer = self.stack.scope(writer)?;
107        if value {
108            writer.write_all(b"true")?;
109        } else {
110            writer.write_all(b"false")?;
111        }
112        Ok(())
113    }
114
115    /// Writes an integer value like `-123` to the specified writer.
116    #[inline]
117    fn write_i8<W>(&mut self, writer: &mut W, value: i8) -> io::Result<()>
118    where
119        W: Write + ?Sized,
120    {
121        CompactFormatter.write_i8(&mut self.stack.scope_with_key(writer)?, value)
122    }
123
124    /// Writes an integer value like `-123` to the specified writer.
125    #[inline]
126    fn write_i16<W>(&mut self, writer: &mut W, value: i16) -> io::Result<()>
127    where
128        W: Write + ?Sized,
129    {
130        CompactFormatter.write_i16(&mut self.stack.scope_with_key(writer)?, value)
131    }
132
133    /// Writes an integer value like `-123` to the specified writer.
134    #[inline]
135    fn write_i32<W>(&mut self, writer: &mut W, value: i32) -> io::Result<()>
136    where
137        W: Write + ?Sized,
138    {
139        CompactFormatter.write_i32(&mut self.stack.scope_with_key(writer)?, value)
140    }
141
142    /// Writes an integer value like `-123` to the specified writer.
143    ///
144    /// Integer `value.abs()` must be safe for JSON: less than `2.pow(53) - 1`
145    #[inline]
146    fn write_i64<W>(&mut self, writer: &mut W, value: i64) -> io::Result<()>
147    where
148        W: Write + ?Sized,
149    {
150        if self.stack.is_in_key()? {
151            CompactFormatter.write_i64(&mut self.stack.scope_with_key(writer)?, value)
152        } else {
153            if value.abs() > MAX_SAFE_INTEGER_I64 {
154                Err(Error::new(
155                    ErrorKind::InvalidData,
156                    "i64.abs() must be less than JSON max safe integer",
157                ))
158            } else {
159                CompactFormatter.write_i64(&mut self.stack.scope(writer)?, value)
160            }
161        }
162    }
163
164    /// Writes an integer value like `-123` to the specified writer.
165    ///
166    /// Integer `value.abs()` must be safe for JSON: less than `2.pow(53) - 1`
167    #[inline]
168    fn write_i128<W>(&mut self, writer: &mut W, value: i128) -> io::Result<()>
169    where
170        W: Write + ?Sized,
171    {
172        if self.stack.is_in_key()? {
173            CompactFormatter.write_i128(&mut self.stack.scope_with_key(writer)?, value)
174        } else {
175            if value.abs() > MAX_SAFE_INTEGER_I128 {
176                Err(Error::new(
177                    ErrorKind::InvalidData,
178                    "i128.abs() must be less than JSON max safe integer",
179                ))
180            } else {
181                CompactFormatter.write_i128(&mut self.stack.scope(writer)?, value)
182            }
183        }
184    }
185
186    /// Writes an integer value like `123` to the specified writer.
187    #[inline]
188    fn write_u8<W>(&mut self, writer: &mut W, value: u8) -> io::Result<()>
189    where
190        W: Write + ?Sized,
191    {
192        CompactFormatter.write_u8(&mut self.stack.scope_with_key(writer)?, value)
193    }
194
195    /// Writes an integer value like `123` to the specified writer.
196    #[inline]
197    fn write_u16<W>(&mut self, writer: &mut W, value: u16) -> io::Result<()>
198    where
199        W: Write + ?Sized,
200    {
201        CompactFormatter.write_u16(&mut self.stack.scope_with_key(writer)?, value)
202    }
203
204    /// Writes an integer value like `123` to the specified writer.
205    #[inline]
206    fn write_u32<W>(&mut self, writer: &mut W, value: u32) -> io::Result<()>
207    where
208        W: Write + ?Sized,
209    {
210        CompactFormatter.write_u32(&mut self.stack.scope_with_key(writer)?, value)
211    }
212
213    /// Writes an integer value like `123` to the specified writer.
214    ///
215    /// Integer `value` must be safe for JSON: less than `2.pow(53) - 1`
216    #[inline]
217    fn write_u64<W>(&mut self, writer: &mut W, value: u64) -> io::Result<()>
218    where
219        W: Write + ?Sized,
220    {
221        if self.stack.is_in_key()? {
222            CompactFormatter.write_u64(&mut self.stack.scope_with_key(writer)?, value)
223        } else {
224            if value > MAX_SAFE_INTEGER_U64 {
225                Err(Error::new(
226                    ErrorKind::InvalidData,
227                    "u64 must be less than JSON max safe integer",
228                ))
229            } else {
230                CompactFormatter.write_u64(&mut self.stack.scope(writer)?, value)
231            }
232        }
233    }
234
235    /// Writes an integer value like `123` to the specified writer.
236    ///
237    /// Integer `value` must be safe for JSON: less than `2.pow(53) - 1`
238    #[inline]
239    fn write_u128<W>(&mut self, writer: &mut W, value: u128) -> io::Result<()>
240    where
241        W: Write + ?Sized,
242    {
243        if self.stack.is_in_key()? {
244            CompactFormatter.write_u128(&mut self.stack.scope_with_key(writer)?, value)
245        } else {
246            if value > MAX_SAFE_INTEGER_U128 {
247                Err(Error::new(
248                    ErrorKind::InvalidData,
249                    "u128 must be less than JSON max safe integer",
250                ))
251            } else {
252                CompactFormatter.write_u128(&mut self.stack.scope(writer)?, value)
253            }
254        }
255    }
256
257    /// Writes a floating point value like `-31.26e+12` to the specified writer.
258    ///
259    /// Follows the [ECMAScript number-to-string] algorithm
260    ///
261    /// [ECMAScript number-to-string]: https://tc39.es/ecma262/#sec-numeric-types-number-tostring
262    #[inline]
263    fn write_f32<W>(&mut self, writer: &mut W, value: f32) -> io::Result<()>
264    where
265        W: Write + ?Sized,
266    {
267        write_float(
268            &mut self.stack.scope_with_key(writer)?,
269            value.classify(),
270            value,
271        )
272    }
273
274    /// Writes a floating point value like `-31.26e+12` to the specified writer.
275    ///
276    /// Follows the [ECMAScript number-to-string] algorithm
277    ///
278    /// [ECMAScript number-to-string]: https://tc39.es/ecma262/#sec-numeric-types-number-tostring
279    #[inline]
280    fn write_f64<W>(&mut self, writer: &mut W, value: f64) -> io::Result<()>
281    where
282        W: Write + ?Sized,
283    {
284        write_float(
285            &mut self.stack.scope_with_key(writer)?,
286            value.classify(),
287            value,
288        )
289    }
290
291    /// Writes a number that has already been rendered to a string.
292    #[inline]
293    fn write_number_str<W>(&mut self, writer: &mut W, value: &str) -> io::Result<()>
294    where
295        W: Write + ?Sized,
296    {
297        let bytes = value.as_bytes();
298        let mut writer = self.stack.scope_with_key(writer)?;
299        writer.write_all(bytes)?;
300        Ok(())
301    }
302
303    /// Called before each series of `write_string_fragment` and `write_char_escape`.
304    ///
305    /// Writes a `"` to the specified writer.
306    #[inline]
307    fn begin_string<W>(&mut self, writer: &mut W) -> io::Result<()>
308    where
309        W: Write + ?Sized,
310    {
311        CompactFormatter.begin_string(&mut self.stack.scope(writer)?)
312    }
313
314    /// Called after each series of `write_string_fragment` and `write_char_escape`.
315    ///
316    /// Writes a `"` to the specified writer.
317    #[inline]
318    fn end_string<W>(&mut self, writer: &mut W) -> io::Result<()>
319    where
320        W: Write + ?Sized,
321    {
322        CompactFormatter.end_string(&mut self.stack.scope(writer)?)
323    }
324
325    /// Writes a string fragment that doesn't need any escaping to the specified writer.
326    #[inline]
327    fn write_string_fragment<W>(&mut self, writer: &mut W, fragment: &str) -> io::Result<()>
328    where
329        W: Write + ?Sized,
330    {
331        let bytes = fragment.as_bytes();
332        let mut writer = self.stack.scope_with_key(writer)?;
333        writer.write_all(bytes)?;
334        Ok(())
335    }
336
337    /// Writes a character escape code to the specified writer.
338    #[inline]
339    fn write_char_escape<W>(&mut self, writer: &mut W, escape: CharEscape) -> io::Result<()>
340    where
341        W: Write + ?Sized,
342    {
343        static HEX_CHARS: [u8; 16] = *b"0123456789abcdef";
344
345        match escape {
346            CharEscape::Backspace => {
347                self.stack.key_bytes()?.write_all(&[0x08])?;
348                self.stack.scope(writer)?.write_all(b"\\b")?;
349            }
350            CharEscape::Tab => {
351                self.stack.key_bytes()?.write_all(&[0x09])?;
352                self.stack.scope(writer)?.write_all(b"\\t")?;
353            }
354            CharEscape::LineFeed => {
355                self.stack.key_bytes()?.write_all(&[0x0A])?;
356                self.stack.scope(writer)?.write_all(b"\\n")?;
357            }
358            CharEscape::FormFeed => {
359                self.stack.key_bytes()?.write_all(&[0x0C])?;
360                self.stack.scope(writer)?.write_all(b"\\f")?;
361            }
362            CharEscape::CarriageReturn => {
363                self.stack.key_bytes()?.write_all(&[0x0D])?;
364                self.stack.scope(writer)?.write_all(b"\\r")?;
365            }
366            CharEscape::Quote => {
367                self.stack.key_bytes()?.write_all(&[0x22])?;
368                self.stack.scope(writer)?.write_all(b"\\\"")?;
369            }
370            CharEscape::Solidus => {
371                self.stack.key_bytes()?.write_all(&[0x2F])?;
372                self.stack.scope(writer)?.write_all(b"\\/")?;
373            }
374            CharEscape::ReverseSolidus => {
375                self.stack.key_bytes()?.write_all(&[0x5C])?;
376                self.stack.scope(writer)?.write_all(b"\\\\")?;
377            }
378            CharEscape::AsciiControl(control) => {
379                self.stack.key_bytes()?.write_all(&[control])?;
380                self.stack.scope(writer)?.write_all(&[
381                    b'\\',
382                    b'u',
383                    b'0',
384                    b'0',
385                    HEX_CHARS[(control >> 4) as usize],
386                    HEX_CHARS[(control & 0xF) as usize],
387                ])?;
388            }
389        }
390        Ok(())
391    }
392
393    /// Called before every array.  Writes a `[` to the specified writer.
394    #[inline]
395    fn begin_array<W>(&mut self, writer: &mut W) -> io::Result<()>
396    where
397        W: Write + ?Sized,
398    {
399        CompactFormatter.begin_array(&mut self.stack.scope(writer)?)
400    }
401
402    /// Called after every array.  Writes a `]` to the specified writer.
403    #[inline]
404    fn end_array<W>(&mut self, writer: &mut W) -> io::Result<()>
405    where
406        W: Write + ?Sized,
407    {
408        CompactFormatter.end_array(&mut self.stack.scope(writer)?)
409    }
410
411    /// Called before every array value.  Writes a `,` if needed to the specified writer.
412    #[inline]
413    fn begin_array_value<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
414    where
415        W: Write + ?Sized,
416    {
417        CompactFormatter.begin_array_value(&mut self.stack.scope(writer)?, first)
418    }
419
420    /// Called after every array value.
421    #[inline]
422    fn end_array_value<W>(&mut self, writer: &mut W) -> io::Result<()>
423    where
424        W: Write + ?Sized,
425    {
426        CompactFormatter.end_array_value(&mut self.stack.scope(writer)?)
427    }
428
429    /// Called before every object.
430    #[inline]
431    fn begin_object<W>(&mut self, _writer: &mut W) -> io::Result<()>
432    where
433        W: Write + ?Sized,
434    {
435        self.stack.start_object();
436        Ok(())
437    }
438
439    /// Called after every object.
440    #[inline]
441    fn end_object<W>(&mut self, writer: &mut W) -> io::Result<()>
442    where
443        W: Write + ?Sized,
444    {
445        self.stack.end_object(writer)
446    }
447
448    /// Called before every object key.
449    #[inline]
450    fn begin_object_key<W>(&mut self, _writer: &mut W, _first: bool) -> io::Result<()>
451    where
452        W: Write + ?Sized,
453    {
454        self.stack.start_key()
455    }
456
457    /// Called after every object key.
458    #[inline]
459    fn end_object_key<W>(&mut self, _writer: &mut W) -> io::Result<()>
460    where
461        W: Write + ?Sized,
462    {
463        self.stack.end_key()
464    }
465
466    /// Called before every object value.
467    #[inline]
468    fn begin_object_value<W>(&mut self, _writer: &mut W) -> io::Result<()>
469    where
470        W: Write + ?Sized,
471    {
472        Ok(())
473    }
474
475    /// Called after every object value.
476    #[inline]
477    fn end_object_value<W>(&mut self, _writer: &mut W) -> io::Result<()>
478    where
479        W: Write + ?Sized,
480    {
481        Ok(())
482    }
483
484    /// Writes a raw JSON fragment that doesn't need any escaping to the specified writer.
485    #[inline]
486    fn write_raw_fragment<W>(&mut self, writer: &mut W, fragment: &str) -> io::Result<()>
487    where
488        W: Write + ?Sized,
489    {
490        let bytes = fragment.as_bytes();
491        let mut writer = self.stack.scope_with_key(writer)?;
492        writer.write_all(bytes)?;
493        Ok(())
494    }
495}
496
497fn write_float<W, F>(writer: &mut W, category: FpCategory, value: F) -> io::Result<()>
498where
499    W: Write + ?Sized,
500    F: ryu_js::Float,
501{
502    match category {
503        FpCategory::Nan => Err(Error::new(ErrorKind::InvalidData, "NaN is not allowed.")),
504        FpCategory::Infinite => Err(Error::new(
505            ErrorKind::InvalidData,
506            "Infinity is not allowed.",
507        )),
508        FpCategory::Zero => writer.write_all(b"0"),
509        FpCategory::Normal | FpCategory::Subnormal => {
510            writer.write_all(ryu_js::Buffer::new().format_finite(value).as_bytes())
511        }
512    }
513}