sonic_rs/
format.rs

1//! Formtter for JSON serialization.
2
3// The code is cloned from [serde_json](https://github.com/serde-rs/json) and modified necessary parts.
4
5use std::io::{self, Write};
6
7use crate::{serde::tri, util::string::format_string, writer::WriteExt};
8
9/// This trait abstracts away serializing the JSON control characters, which allows the user to
10/// optionally pretty print the JSON output.
11pub trait Formatter: Clone {
12    /// Writes a `null` value to the specified writer.
13    #[inline]
14    fn write_null<W>(&mut self, writer: &mut W) -> io::Result<()>
15    where
16        W: ?Sized + Write,
17    {
18        writer.write_all(b"null")
19    }
20
21    /// Writes a `true` or `false` value to the specified writer.
22    #[inline]
23    fn write_bool<W>(&mut self, writer: &mut W, value: bool) -> io::Result<()>
24    where
25        W: ?Sized + Write,
26    {
27        if value {
28            writer.write_all(b"true")
29        } else {
30            writer.write_all(b"false")
31        }
32    }
33
34    /// Writes an integer value like `-123` to the specified writer.
35    #[inline]
36    fn write_i8<W>(&mut self, writer: &mut W, value: i8) -> io::Result<()>
37    where
38        W: ?Sized + Write,
39    {
40        let mut buffer = itoa::Buffer::new();
41        let s = buffer.format(value);
42        writer.write_all(s.as_bytes())
43    }
44
45    /// Writes an integer value like `-123` to the specified writer.
46    #[inline]
47    fn write_i16<W>(&mut self, writer: &mut W, value: i16) -> io::Result<()>
48    where
49        W: ?Sized + Write,
50    {
51        let mut buffer = itoa::Buffer::new();
52        let s = buffer.format(value);
53        writer.write_all(s.as_bytes())
54    }
55
56    /// Writes an integer value like `-123` to the specified writer.
57    #[inline]
58    fn write_i32<W>(&mut self, writer: &mut W, value: i32) -> io::Result<()>
59    where
60        W: ?Sized + Write,
61    {
62        let mut buffer = itoa::Buffer::new();
63        let s = buffer.format(value);
64        writer.write_all(s.as_bytes())
65    }
66
67    /// Writes an integer value like `-123` to the specified writer.
68    #[inline]
69    fn write_i64<W>(&mut self, writer: &mut W, value: i64) -> io::Result<()>
70    where
71        W: ?Sized + Write,
72    {
73        let mut buffer = itoa::Buffer::new();
74        let s = buffer.format(value);
75        writer.write_all(s.as_bytes())
76    }
77
78    /// Writes an integer value like `-123` to the specified writer.
79    #[inline]
80    fn write_i128<W>(&mut self, writer: &mut W, value: i128) -> io::Result<()>
81    where
82        W: ?Sized + Write,
83    {
84        let mut buffer = itoa::Buffer::new();
85        let s = buffer.format(value);
86        writer.write_all(s.as_bytes())
87    }
88
89    /// Writes an integer value like `123` to the specified writer.
90    #[inline]
91    fn write_u8<W>(&mut self, writer: &mut W, value: u8) -> io::Result<()>
92    where
93        W: ?Sized + Write,
94    {
95        let mut buffer = itoa::Buffer::new();
96        let s = buffer.format(value);
97        writer.write_all(s.as_bytes())
98    }
99
100    /// Writes an integer value like `123` to the specified writer.
101    #[inline]
102    fn write_u16<W>(&mut self, writer: &mut W, value: u16) -> io::Result<()>
103    where
104        W: ?Sized + Write,
105    {
106        let mut buffer = itoa::Buffer::new();
107        let s = buffer.format(value);
108        writer.write_all(s.as_bytes())
109    }
110
111    /// Writes an integer value like `123` to the specified writer.
112    #[inline]
113    fn write_u32<W>(&mut self, writer: &mut W, value: u32) -> io::Result<()>
114    where
115        W: ?Sized + Write,
116    {
117        let mut buffer = itoa::Buffer::new();
118        let s = buffer.format(value);
119        writer.write_all(s.as_bytes())
120    }
121
122    /// Writes an integer value like `123` to the specified writer.
123    #[inline]
124    fn write_u64<W>(&mut self, writer: &mut W, value: u64) -> io::Result<()>
125    where
126        W: ?Sized + Write,
127    {
128        let mut buffer = itoa::Buffer::new();
129        let s = buffer.format(value);
130        writer.write_all(s.as_bytes())
131    }
132
133    /// Writes an integer value like `123` to the specified writer.
134    #[inline]
135    fn write_u128<W>(&mut self, writer: &mut W, value: u128) -> io::Result<()>
136    where
137        W: ?Sized + Write,
138    {
139        let mut buffer = itoa::Buffer::new();
140        let s = buffer.format(value);
141        writer.write_all(s.as_bytes())
142    }
143
144    /// Writes a floating point value like `-31.26e+12` to the specified writer.
145    #[inline]
146    fn write_f32<W>(&mut self, writer: &mut W, value: f32) -> io::Result<()>
147    where
148        W: ?Sized + Write,
149    {
150        #[cfg(feature = "non_trailing_zero")]
151        if value.fract() == 0.0 && value <= (i64::MAX as f32) && value >= (i64::MIN as f32) {
152            return self.write_i64(writer, value as i64);
153        }
154
155        let mut buffer = ryu::Buffer::new();
156        let s = buffer.format_finite(value);
157        writer.write_all(s.as_bytes())
158    }
159
160    /// Writes a floating point value like `-31.26e+12` to the specified writer.
161    #[inline]
162    fn write_f64<W>(&mut self, writer: &mut W, value: f64) -> io::Result<()>
163    where
164        W: ?Sized + Write,
165    {
166        #[cfg(feature = "non_trailing_zero")]
167        if value.fract() == 0.0 && value <= (i64::MAX as f64) && value >= (i64::MIN as f64) {
168            return self.write_i64(writer, value as i64);
169        }
170
171        let mut buffer = ryu::Buffer::new();
172        let s = buffer.format_finite(value);
173        writer.write_all(s.as_bytes())
174    }
175
176    /// Writes a number that has already been rendered to a string.
177    #[inline]
178    fn write_number_str<W>(&mut self, writer: &mut W, value: &str) -> io::Result<()>
179    where
180        W: ?Sized + Write,
181    {
182        writer.write_all(value.as_bytes())
183    }
184
185    /// Writes a string as JSON string to the specified writer. Will escape the string if necessary.
186    /// If `need_quote` is `false`, the string will be written without quotes.
187    #[inline]
188    fn write_string_fast<W>(
189        &mut self,
190        writer: &mut W,
191        value: &str,
192        need_quote: bool,
193    ) -> io::Result<()>
194    where
195        W: ?Sized + WriteExt,
196    {
197        let buf = writer.reserve_with(value.len() * 6 + 32 + 3)?;
198        let cnt = format_string(value, buf, need_quote);
199        unsafe { writer.flush_len(cnt)? };
200        Ok(())
201    }
202
203    /// Writes the representation of a byte array. Formatters can choose whether
204    /// to represent bytes as a JSON array of integers (the default), or some
205    /// JSON string encoding like hex or base64.
206    fn write_byte_array<W>(&mut self, writer: &mut W, value: &[u8]) -> io::Result<()>
207    where
208        W: ?Sized + Write,
209    {
210        tri!(self.begin_array(writer));
211        let mut first = true;
212        for byte in value {
213            tri!(self.begin_array_value(writer, first));
214            tri!(self.write_u8(writer, *byte));
215            tri!(self.end_array_value(writer));
216            first = false;
217        }
218        self.end_array(writer)
219    }
220
221    /// Only called before stringifing some values, such as integer key in HashMap
222    #[inline]
223    fn begin_string<W>(&mut self, writer: &mut W) -> io::Result<()>
224    where
225        W: ?Sized + Write,
226    {
227        writer.write_all(b"\"")
228    }
229
230    /// Only called after stringifing some values, such as integer key in HashMap
231    #[inline]
232    fn end_string<W>(&mut self, writer: &mut W) -> io::Result<()>
233    where
234        W: ?Sized + Write,
235    {
236        writer.write_all(b"\"")
237    }
238
239    /// Called before every array.  Writes a `[` to the specified
240    /// writer.
241    #[inline]
242    fn begin_array<W>(&mut self, writer: &mut W) -> io::Result<()>
243    where
244        W: ?Sized + Write,
245    {
246        writer.write_all(b"[")
247    }
248
249    /// Called after every array.  Writes a `]` to the specified
250    /// writer.
251    #[inline]
252    fn end_array<W>(&mut self, writer: &mut W) -> io::Result<()>
253    where
254        W: ?Sized + Write,
255    {
256        writer.write_all(b"]")
257    }
258
259    /// Called before every array value.  Writes a `,` if needed to
260    /// the specified writer.
261    #[inline]
262    fn begin_array_value<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
263    where
264        W: ?Sized + Write,
265    {
266        if first {
267            Ok(())
268        } else {
269            writer.write_all(b",")
270        }
271    }
272
273    /// Called after every array value.
274    #[inline]
275    fn end_array_value<W>(&mut self, _writer: &mut W) -> io::Result<()>
276    where
277        W: ?Sized + Write,
278    {
279        Ok(())
280    }
281
282    /// Called before every object.  Writes a `{` to the specified
283    /// writer.
284    #[inline]
285    fn begin_object<W>(&mut self, writer: &mut W) -> io::Result<()>
286    where
287        W: ?Sized + Write,
288    {
289        writer.write_all(b"{")
290    }
291
292    /// Called after every object.  Writes a `}` to the specified
293    /// writer.
294    #[inline]
295    fn end_object<W>(&mut self, writer: &mut W) -> io::Result<()>
296    where
297        W: ?Sized + Write,
298    {
299        writer.write_all(b"}")
300    }
301
302    /// Called before every object key.
303    #[inline]
304    fn begin_object_key<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
305    where
306        W: ?Sized + Write,
307    {
308        if first {
309            Ok(())
310        } else {
311            writer.write_all(b",")
312        }
313    }
314
315    /// Called after every object key.  A `:` should be written to the
316    /// specified writer by either this method or
317    /// `begin_object_value`.
318    #[inline]
319    fn end_object_key<W>(&mut self, _writer: &mut W) -> io::Result<()>
320    where
321        W: ?Sized + Write,
322    {
323        Ok(())
324    }
325
326    /// Called before every object value.  A `:` should be written to
327    /// the specified writer by either this method or
328    /// `end_object_key`.
329    #[inline]
330    fn begin_object_value<W>(&mut self, writer: &mut W) -> io::Result<()>
331    where
332        W: ?Sized + Write,
333    {
334        writer.write_all(b":")
335    }
336
337    /// Called after every object value.
338    #[inline]
339    fn end_object_value<W>(&mut self, _writer: &mut W) -> io::Result<()>
340    where
341        W: ?Sized + Write,
342    {
343        Ok(())
344    }
345
346    /// Writes a raw JSON value that doesn't need any escaping to the
347    /// specified writer.
348    #[inline]
349    fn write_raw_value<W>(&mut self, writer: &mut W, raw: &str) -> io::Result<()>
350    where
351        W: ?Sized + Write,
352    {
353        writer.write_all(raw.as_bytes())
354    }
355}
356
357/// This structure compacts a JSON value with no extra whitespace.
358#[derive(Clone, Debug)]
359pub struct CompactFormatter;
360
361impl Formatter for CompactFormatter {}
362
363/// This structure pretty prints a JSON value to make it human readable.
364#[derive(Clone, Debug)]
365pub struct PrettyFormatter<'a> {
366    current_indent: usize,
367    has_value: bool,
368    indent: &'a [u8],
369}
370
371impl<'a> PrettyFormatter<'a> {
372    /// Construct a pretty printer formatter that defaults to using two spaces for indentation.
373    pub fn new() -> Self {
374        PrettyFormatter::with_indent(b"  ")
375    }
376
377    /// Construct a pretty printer formatter that uses the `indent` string for indentation.
378    pub fn with_indent(indent: &'a [u8]) -> Self {
379        PrettyFormatter {
380            current_indent: 0,
381            has_value: false,
382            indent,
383        }
384    }
385}
386
387impl<'a> Default for PrettyFormatter<'a> {
388    fn default() -> Self {
389        PrettyFormatter::new()
390    }
391}
392
393impl<'a> Formatter for PrettyFormatter<'a> {
394    #[inline]
395    fn begin_array<W>(&mut self, writer: &mut W) -> io::Result<()>
396    where
397        W: ?Sized + Write,
398    {
399        self.current_indent += 1;
400        self.has_value = false;
401        writer.write_all(b"[")
402    }
403
404    #[inline]
405    fn end_array<W>(&mut self, writer: &mut W) -> io::Result<()>
406    where
407        W: ?Sized + Write,
408    {
409        self.current_indent -= 1;
410
411        if self.has_value {
412            tri!(writer.write_all(b"\n"));
413            tri!(indent(writer, self.current_indent, self.indent));
414        }
415
416        writer.write_all(b"]")
417    }
418
419    #[inline]
420    fn begin_array_value<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
421    where
422        W: ?Sized + Write,
423    {
424        tri!(writer.write_all(if first { b"\n" } else { b",\n" }));
425        indent(writer, self.current_indent, self.indent)
426    }
427
428    #[inline]
429    fn end_array_value<W>(&mut self, _writer: &mut W) -> io::Result<()>
430    where
431        W: ?Sized + Write,
432    {
433        self.has_value = true;
434        Ok(())
435    }
436
437    #[inline]
438    fn begin_object<W>(&mut self, writer: &mut W) -> io::Result<()>
439    where
440        W: ?Sized + Write,
441    {
442        self.current_indent += 1;
443        self.has_value = false;
444        writer.write_all(b"{")
445    }
446
447    #[inline]
448    fn end_object<W>(&mut self, writer: &mut W) -> io::Result<()>
449    where
450        W: ?Sized + Write,
451    {
452        self.current_indent -= 1;
453
454        if self.has_value {
455            tri!(writer.write_all(b"\n"));
456            tri!(indent(writer, self.current_indent, self.indent));
457        }
458
459        writer.write_all(b"}")
460    }
461
462    #[inline]
463    fn begin_object_key<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
464    where
465        W: ?Sized + Write,
466    {
467        tri!(writer.write_all(if first { b"\n" } else { b",\n" }));
468        indent(writer, self.current_indent, self.indent)
469    }
470
471    #[inline]
472    fn begin_object_value<W>(&mut self, writer: &mut W) -> io::Result<()>
473    where
474        W: ?Sized + Write,
475    {
476        writer.write_all(b": ")
477    }
478
479    #[inline]
480    fn end_object_value<W>(&mut self, _writer: &mut W) -> io::Result<()>
481    where
482        W: ?Sized + Write,
483    {
484        self.has_value = true;
485        Ok(())
486    }
487}
488
489fn indent<W>(wr: &mut W, n: usize, s: &[u8]) -> io::Result<()>
490where
491    W: ?Sized + Write,
492{
493    for _ in 0..n {
494        tri!(wr.write_all(s));
495    }
496
497    Ok(())
498}