Skip to main content

sark_json/
encode.rs

1use std::convert::Infallible;
2
3use o3::buffer::ByteSink;
4
5pub trait Write: ByteSink {
6    fn put(&mut self, src: &[u8]) -> Result<(), Self::Error> {
7        self.write_slice(src)
8    }
9
10    fn put_str(&mut self, value: &[u8]) -> Result<(), Self::Error> {
11        self.put(b"\"")?;
12        let mut start = 0usize;
13        let mut idx = 0usize;
14        while idx < value.len() {
15            if let Some(token) = Encode::esc_token(value[idx]) {
16                if start != idx {
17                    self.put(&value[start..idx])?;
18                }
19                self.put(token.as_bytes())?;
20                idx += 1;
21                start = idx;
22                continue;
23            }
24            idx += 1;
25        }
26        if start != value.len() {
27            self.put(&value[start..])?;
28        }
29        self.put(b"\"")
30    }
31
32    fn put_str_plain(&mut self, value: &[u8]) -> Result<(), Self::Error> {
33        self.write_slices([b"\"".as_slice(), value, b"\"".as_slice()])
34    }
35
36    fn put_u64(&mut self, value: u64) -> Result<(), Self::Error> {
37        if value == 0 {
38            return self.put(b"0");
39        }
40        let mut digits = [0u8; 20];
41        let mut idx = digits.len();
42        let mut value = value;
43        while value != 0 {
44            idx -= 1;
45            digits[idx] = b'0' + (value % 10) as u8;
46            value /= 10;
47        }
48        self.put(&digits[idx..])
49    }
50
51    fn put_i64(&mut self, value: i64) -> Result<(), Self::Error> {
52        if value < 0 {
53            self.put(b"-")?;
54        }
55        self.put_u64(value.unsigned_abs())
56    }
57
58    fn put_f64(&mut self, value: f64) -> Result<(), Self::Error> {
59        if value.is_finite() {
60            self.put(ryu::Buffer::new().format_finite(value).as_bytes())
61        } else {
62            self.put(b"null")
63        }
64    }
65}
66
67impl<W: ByteSink + ?Sized> Write for W {}
68
69pub struct Writer<'a> {
70    inner: &'a mut Vec<u8>,
71    start: usize,
72}
73
74impl<'a> Writer<'a> {
75    pub fn new(buf: &'a mut Vec<u8>, estimate: usize) -> Self {
76        let start = buf.len();
77        buf.reserve(estimate);
78        Self { inner: buf, start }
79    }
80
81    pub fn finish(self) -> usize {
82        self.inner.len() - self.start
83    }
84}
85
86impl ByteSink for Writer<'_> {
87    type Error = Infallible;
88
89    fn write_slices<const N: usize>(&mut self, slices: [&[u8]; N]) -> Result<(), Self::Error> {
90        self.inner.write_slices(slices)
91    }
92}
93
94pub struct Encode;
95
96impl Encode {
97    pub fn u64_len(mut value: u64) -> usize {
98        if value == 0 {
99            return 1;
100        }
101        let mut digits = 0usize;
102        while value != 0 {
103            digits += 1;
104            value /= 10;
105        }
106        digits
107    }
108
109    pub fn i64_len(value: i64) -> usize {
110        Self::u64_len(value.unsigned_abs()) + usize::from(value < 0)
111    }
112
113    pub fn f64_len(value: f64) -> usize {
114        if value.is_finite() {
115            ryu::Buffer::new().format_finite(value).len()
116        } else {
117            4
118        }
119    }
120
121    pub fn str_len(value: &[u8]) -> usize {
122        2 + Self::esc_len(value)
123    }
124
125    fn esc_len(value: &[u8]) -> usize {
126        let mut len = 0usize;
127        let mut idx = 0usize;
128        while idx < value.len() {
129            len += Self::esc_size(value[idx]);
130            idx += 1;
131        }
132        len
133    }
134
135    fn esc_size(byte: u8) -> usize {
136        match Self::esc_token(byte) {
137            Some(token) => token.len(),
138            None => 1,
139        }
140    }
141
142    fn esc_token(byte: u8) -> Option<&'static str> {
143        match byte {
144            b'"' => Some("\\\""),
145            b'\\' => Some("\\\\"),
146            b'\n' => Some("\\n"),
147            b'\r' => Some("\\r"),
148            b'\t' => Some("\\t"),
149            0x00 => Some("\\u0000"),
150            0x01 => Some("\\u0001"),
151            0x02 => Some("\\u0002"),
152            0x03 => Some("\\u0003"),
153            0x04 => Some("\\u0004"),
154            0x05 => Some("\\u0005"),
155            0x06 => Some("\\u0006"),
156            0x07 => Some("\\u0007"),
157            0x08 => Some("\\b"),
158            0x0b => Some("\\u000b"),
159            0x0c => Some("\\f"),
160            0x0e => Some("\\u000e"),
161            0x0f => Some("\\u000f"),
162            0x10 => Some("\\u0010"),
163            0x11 => Some("\\u0011"),
164            0x12 => Some("\\u0012"),
165            0x13 => Some("\\u0013"),
166            0x14 => Some("\\u0014"),
167            0x15 => Some("\\u0015"),
168            0x16 => Some("\\u0016"),
169            0x17 => Some("\\u0017"),
170            0x18 => Some("\\u0018"),
171            0x19 => Some("\\u0019"),
172            0x1a => Some("\\u001a"),
173            0x1b => Some("\\u001b"),
174            0x1c => Some("\\u001c"),
175            0x1d => Some("\\u001d"),
176            0x1e => Some("\\u001e"),
177            0x1f => Some("\\u001f"),
178            _ => None,
179        }
180    }
181}