Skip to main content

sark_json/
encode.rs

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