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}