1use core::fmt::{self, Write};
2
3use crate::{Error, Result};
4
5macro_rules! integer_writer {
6 ($name:ident, $ty:ty) => {
7 pub fn $name(&mut self, value: $ty) -> Result<()> {
8 write_display(self, value)
9 }
10 };
11}
12
13#[derive(Clone, Copy, Eq, PartialEq)]
14enum FrameKind {
15 Object,
16 Array,
17}
18
19#[derive(Clone, Copy)]
20struct Frame {
21 kind: FrameKind,
22 first: bool,
23 expecting_value: bool,
24}
25
26impl Frame {
27 #[inline]
28 const fn new(kind: FrameKind) -> Self {
29 Self {
30 kind,
31 first: true,
32 expecting_value: false,
33 }
34 }
35}
36
37pub struct JsonSerializer<'a, const DEPTH: usize> {
42 out: &'a mut [u8],
43 len: usize,
44 stack: [Frame; DEPTH],
45 depth: usize,
46 root_written: bool,
47}
48
49impl<'a, const DEPTH: usize> JsonSerializer<'a, DEPTH> {
50 #[inline]
51 pub fn new(out: &'a mut [u8]) -> Self {
52 Self {
53 out,
54 len: 0,
55 stack: [Frame::new(FrameKind::Array); DEPTH],
56 depth: 0,
57 root_written: false,
58 }
59 }
60
61 #[inline]
62 pub fn len(&self) -> usize {
63 self.len
64 }
65
66 #[inline]
67 pub fn is_empty(&self) -> bool {
68 self.len == 0
69 }
70
71 #[inline]
72 pub fn capacity(&self) -> usize {
73 self.out.len()
74 }
75
76 #[inline]
77 pub fn as_str(&self) -> &str {
78 unsafe { core::str::from_utf8_unchecked(&self.out[..self.len]) }
81 }
82
83 #[inline]
84 pub fn finish(&self) -> Result<&str> {
85 if self.depth == 0 && self.root_written {
86 Ok(self.as_str())
87 } else if self.depth == 0 {
88 Err(Error::BadSerialize)
89 } else {
90 Err(Error::NestMismatch)
91 }
92 }
93
94 #[inline]
95 pub fn reset(&mut self) {
96 self.len = 0;
97 self.depth = 0;
98 self.root_written = false;
99 }
100
101 pub fn begin_object(&mut self) -> Result<()> {
102 begin_container(self, FrameKind::Object, b'{')
103 }
104
105 pub fn end_object(&mut self) -> Result<()> {
106 end_container(self, FrameKind::Object, b'}')
107 }
108
109 pub fn begin_array(&mut self) -> Result<()> {
110 begin_container(self, FrameKind::Array, b'[')
111 }
112
113 pub fn end_array(&mut self) -> Result<()> {
114 end_container(self, FrameKind::Array, b']')
115 }
116
117 pub fn key(&mut self, key: &str) -> Result<()> {
118 let frame = current_frame_mut(self)?;
119 if frame.kind != FrameKind::Object || frame.expecting_value {
120 return Err(Error::BadSerialize);
121 }
122 if !frame.first {
123 write_byte(self, b',')?;
124 }
125 current_frame_mut(self)?.first = false;
126 write_quoted(self, key)?;
127 write_byte(self, b':')?;
128 current_frame_mut(self)?.expecting_value = true;
129 Ok(())
130 }
131
132 pub fn null(&mut self) -> Result<()> {
133 write_value_str(self, "null")
134 }
135
136 pub fn bool(&mut self, value: bool) -> Result<()> {
137 write_value_str(self, if value { "true" } else { "false" })
138 }
139
140 pub fn string(&mut self, value: &str) -> Result<()> {
141 before_value(self)?;
142 write_quoted(self, value)
143 }
144
145 integer_writer!(i16, i16);
146 integer_writer!(u16, u16);
147 integer_writer!(i32, i32);
148 integer_writer!(u32, u32);
149 integer_writer!(i64, i64);
150 integer_writer!(u64, u64);
151
152 pub fn f64(&mut self, value: f64) -> Result<()> {
153 if !value.is_finite() {
154 return Err(Error::BadNum);
155 }
156 write_display(self, value)
157 }
158
159 pub fn raw_number(&mut self, number: &str) -> Result<()> {
160 if !json_number(number.as_bytes()) {
161 return Err(Error::BadNum);
162 }
163 write_value_str(self, number)
164 }
165}
166
167fn begin_container<const DEPTH: usize>(
168 serializer: &mut JsonSerializer<'_, DEPTH>,
169 kind: FrameKind,
170 open: u8,
171) -> Result<()> {
172 if serializer.depth == DEPTH {
173 return Err(Error::NestTooDeep);
174 }
175 before_value(serializer)?;
176 write_byte(serializer, open)?;
177 serializer.stack[serializer.depth] = Frame::new(kind);
178 serializer.depth += 1;
179 Ok(())
180}
181
182fn end_container<const DEPTH: usize>(
183 serializer: &mut JsonSerializer<'_, DEPTH>,
184 kind: FrameKind,
185 close: u8,
186) -> Result<()> {
187 if serializer.depth == 0 {
188 return Err(Error::NestMismatch);
189 }
190 let frame = serializer.stack[serializer.depth - 1];
191 if frame.kind != kind || frame.expecting_value {
192 return Err(Error::NestMismatch);
193 }
194 serializer.depth -= 1;
195 write_byte(serializer, close)
196}
197
198fn before_value<const DEPTH: usize>(serializer: &mut JsonSerializer<'_, DEPTH>) -> Result<()> {
199 if serializer.depth == 0 {
200 if serializer.root_written {
201 return Err(Error::BadSerialize);
202 }
203 serializer.root_written = true;
204 return Ok(());
205 }
206
207 let frame = &mut serializer.stack[serializer.depth - 1];
208 match frame.kind {
209 FrameKind::Array => {
210 if !frame.first {
211 write_byte(serializer, b',')?;
212 }
213 serializer.stack[serializer.depth - 1].first = false;
214 Ok(())
215 }
216 FrameKind::Object if frame.expecting_value => {
217 serializer.stack[serializer.depth - 1].expecting_value = false;
218 Ok(())
219 }
220 FrameKind::Object => Err(Error::BadSerialize),
221 }
222}
223
224#[inline]
225fn current_frame_mut<'s, 'out, const DEPTH: usize>(
226 serializer: &'s mut JsonSerializer<'out, DEPTH>,
227) -> Result<&'s mut Frame> {
228 if serializer.depth == 0 {
229 Err(Error::BadSerialize)
230 } else {
231 Ok(&mut serializer.stack[serializer.depth - 1])
232 }
233}
234
235fn write_value_str<const DEPTH: usize>(
236 serializer: &mut JsonSerializer<'_, DEPTH>,
237 value: &str,
238) -> Result<()> {
239 before_value(serializer)?;
240 write_raw_str(serializer, value)
241}
242
243fn write_display<const DEPTH: usize>(
244 serializer: &mut JsonSerializer<'_, DEPTH>,
245 value: impl fmt::Display,
246) -> Result<()> {
247 before_value(serializer)?;
248 write!(serializer, "{value}").map_err(|_| Error::WriteLong)
249}
250
251fn write_quoted<const DEPTH: usize>(
252 serializer: &mut JsonSerializer<'_, DEPTH>,
253 value: &str,
254) -> Result<()> {
255 write_byte(serializer, b'"')?;
256 for ch in value.chars() {
257 match ch {
258 '"' => write_raw_str(serializer, "\\\"")?,
259 '\\' => write_raw_str(serializer, "\\\\")?,
260 '\u{08}' => write_raw_str(serializer, "\\b")?,
261 '\u{0c}' => write_raw_str(serializer, "\\f")?,
262 '\n' => write_raw_str(serializer, "\\n")?,
263 '\r' => write_raw_str(serializer, "\\r")?,
264 '\t' => write_raw_str(serializer, "\\t")?,
265 '\u{00}'..='\u{1f}' => {
266 write_raw_str(serializer, "\\u00")?;
267 write_hex_digit(serializer, (ch as u8) >> 4)?;
268 write_hex_digit(serializer, ch as u8)?;
269 }
270 _ => write_raw_str(serializer, ch.encode_utf8(&mut [0; 4]))?,
271 }
272 }
273 write_byte(serializer, b'"')
274}
275
276#[inline]
277fn write_hex_digit<const DEPTH: usize>(
278 serializer: &mut JsonSerializer<'_, DEPTH>,
279 value: u8,
280) -> Result<()> {
281 const HEX: &[u8; 16] = b"0123456789abcdef";
282 write_byte(serializer, HEX[(value & 0x0f) as usize])
283}
284
285#[inline]
286fn write_byte<const DEPTH: usize>(
287 serializer: &mut JsonSerializer<'_, DEPTH>,
288 byte: u8,
289) -> Result<()> {
290 if serializer.len == serializer.out.len() {
291 return Err(Error::WriteLong);
292 }
293 serializer.out[serializer.len] = byte;
294 serializer.len += 1;
295 Ok(())
296}
297
298#[inline]
299fn write_raw_str<const DEPTH: usize>(
300 serializer: &mut JsonSerializer<'_, DEPTH>,
301 value: &str,
302) -> Result<()> {
303 if serializer.out.len() - serializer.len < value.len() {
304 return Err(Error::WriteLong);
305 }
306 serializer.out[serializer.len..serializer.len + value.len()].copy_from_slice(value.as_bytes());
307 serializer.len += value.len();
308 Ok(())
309}
310
311impl<const DEPTH: usize> fmt::Write for JsonSerializer<'_, DEPTH> {
312 #[inline]
313 fn write_str(&mut self, s: &str) -> fmt::Result {
314 write_raw_str(self, s).map_err(|_| fmt::Error)
315 }
316}
317
318fn json_number(bytes: &[u8]) -> bool {
319 if bytes.is_empty() {
320 return false;
321 }
322 let mut i = 0usize;
323 if bytes[i] == b'-' {
324 i += 1;
325 }
326 if i >= bytes.len() || !bytes[i].is_ascii_digit() {
327 return false;
328 }
329 if bytes[i] == b'0' {
330 i += 1;
331 if i < bytes.len() && bytes[i].is_ascii_digit() {
332 return false;
333 }
334 } else {
335 while i < bytes.len() && bytes[i].is_ascii_digit() {
336 i += 1;
337 }
338 }
339 if i < bytes.len() && bytes[i] == b'.' {
340 i += 1;
341 if i >= bytes.len() || !bytes[i].is_ascii_digit() {
342 return false;
343 }
344 while i < bytes.len() && bytes[i].is_ascii_digit() {
345 i += 1;
346 }
347 }
348 if i < bytes.len() && matches!(bytes[i], b'e' | b'E') {
349 i += 1;
350 if i < bytes.len() && matches!(bytes[i], b'+' | b'-') {
351 i += 1;
352 }
353 if i >= bytes.len() || !bytes[i].is_ascii_digit() {
354 return false;
355 }
356 while i < bytes.len() && bytes[i].is_ascii_digit() {
357 i += 1;
358 }
359 }
360 i == bytes.len()
361}