1use crate::shared::*;
2use crate::nonblocking::io::NonBlockingWrite;
3use core::fmt::Display;
4use core::marker::PhantomData;
5
6pub struct JsonWriter <'a, W: NonBlockingWrite, F: JsonFormatter, FF: FloatFormat> {
12 inner: &'a mut W,
13 formatter: F,
14 number_write_buf: NumWriteBuf,
15 _float_format: FF,
16}
17
18impl <'a, W: NonBlockingWrite, F: JsonFormatter, FF: FloatFormat> JsonWriter<'a, W, F, FF> {
19 pub fn new(inner: &'a mut W, formatter: F, float_format: FF) -> JsonWriter<'a, W, F, FF> {
23 JsonWriter {
24 inner,
25 formatter,
26 number_write_buf: NumWriteBuf::new(),
27 _float_format: float_format,
28 }
29 }
30
31 pub async fn write_bytes(&mut self, data: &[u8]) -> Result<(), W::Error> {
33 self.inner.write_all(data).await
34 }
35
36 pub async fn write_escaped_string(&mut self, s: &str) -> Result<(), W::Error> {
38 self.write_bytes(b"\"").await?;
39 for b in s.bytes() {
40 match b {
41 b'"' => self.write_bytes(b"\\\"").await?,
42 b'\\' => self.write_bytes(b"\\\\").await?,
43 b'\x08' => self.write_bytes(b"\\b").await?,
44 b'\x0c' => self.write_bytes(b"\\f").await?,
45 b'\n' => self.write_bytes(b"\\n").await?,
46 b'\r' => self.write_bytes(b"\\r").await?,
47 b'\t' => self.write_bytes(b"\\t").await?,
48 b if b < 0x20 => {
49 static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
50 let bytes = &[
51 b'\\',
52 b'u',
53 b'0',
54 b'0',
55 HEX_DIGITS[(b >> 4) as usize],
56 HEX_DIGITS[(b & 0xF) as usize],
57 ];
58 self.write_bytes(bytes).await?
59 },
60 b => self.write_bytes(&[b]).await?,
61 }
62 }
63 self.write_bytes(b"\"").await?;
64 Ok(())
65 }
66
67 pub async fn write_bool(&mut self, value: bool) -> Result<(), W::Error> {
69 if value {
70 self.write_bytes(b"true").await
71 }
72 else {
73 self.write_bytes(b"false").await
74 }
75 }
76
77 pub async fn write_f64(&mut self, value: f64) -> Result<(), W::Error> {
79 FormatWrapper::new(self)
80 .write_f64(value).await
81 }
82
83 pub async fn write_f32(&mut self, value: f32) -> Result<(), W::Error> {
85 FormatWrapper::new(self)
86 .write_f32(value).await
87 }
88
89 pub async fn write_raw_num(&mut self, value: impl Display) -> Result<(), W::Error> {
91 FormatWrapper::new(self)
92 .write_raw(value).await
93 }
94
95 pub async fn write_format_after_key(&mut self) -> Result<(), W::Error> {
97 self.inner.write_all(self.formatter.after_key().as_bytes()).await
98 }
99
100 pub async fn write_format_after_start_nested(&mut self) -> Result<(), W::Error> {
102 self.inner.write_all(self.formatter.after_start_nested().as_bytes()).await
103 }
104
105 pub async fn write_format_after_element(&mut self) -> Result<(), W::Error> {
107 self.inner.write_all(self.formatter.after_element().as_bytes()).await
108 }
109
110 pub async fn write_format_before_end_nested(&mut self, is_empty: bool) -> Result<(), W::Error> {
112 self.inner.write_all(self.formatter.before_end_nested(is_empty).as_bytes()).await
113 }
114
115 pub async fn write_format_indent(&mut self) -> Result<(), W::Error> {
117 self.inner.write_all(self.formatter.indent().as_bytes()).await
118 }
119
120 pub fn into_inner(self) -> Result<&'a mut W, W::Error> {
123 Ok(self.inner)
124 }
125}
126
127impl <'a, W: NonBlockingWrite> JsonWriter<'a, W, CompactFormatter, DefaultFloatFormat> {
128 pub fn new_compact(inner: &'a mut W) -> Self {
130 JsonWriter::new(inner, CompactFormatter, DefaultFloatFormat)
131 }
132}
133
134impl <'a, W: NonBlockingWrite> JsonWriter<'a, W, PrettyFormatter, DefaultFloatFormat> {
135 pub fn new_pretty(inner: &'a mut W) -> Self {
137 JsonWriter::new(inner, PrettyFormatter::new(), DefaultFloatFormat)
138 }
139}
140
141struct NumWriteBuf {
142 buf: [u8;40],
143 len: usize,
144}
145
146impl NumWriteBuf {
147 fn new() -> Self {
148 Self {
149 buf: [0u8;40],
150 len: 0,
151 }
152 }
153
154 fn as_bytes(&self) -> &[u8] {
155 &self.buf[..self.len]
156 }
157
158 fn reset(&mut self) {
159 self.len = 0;
160 }
161}
162impl core::fmt::Write for NumWriteBuf {
163 fn write_str(&mut self, s: &str) -> core::fmt::Result {
164 let old_len = self.len;
165 self.len += s.len();
166 self.buf[old_len..self.len].copy_from_slice(s.as_bytes());
167 Ok(())
168 }
169}
170
171struct FormatWrapper<'a, W: NonBlockingWrite, FF: FloatFormat> {
172 buf: &'a mut NumWriteBuf,
173 writer: &'a mut W,
174 pd: PhantomData<FF>,
175}
176impl<'a, W: NonBlockingWrite, FF: FloatFormat> FormatWrapper<'a, W, FF> {
177 fn new<F: JsonFormatter>(inner: &'a mut JsonWriter<W, F, FF>) -> Self {
178 inner.number_write_buf.reset();
179 Self {
180 buf: &mut inner.number_write_buf,
181 writer: &mut inner.inner,
182 pd: PhantomData::default(),
183 }
184 }
185
186 async fn write_raw(&mut self, value: impl Display) -> Result<(), W::Error> {
187 use core::fmt::Write;
188
189 let _ = write!(&mut self.buf, "{}", value);
190 self.writer.write_all(&self.buf.as_bytes()).await
191 }
192
193 async fn write_f64(&mut self, value: f64) -> Result<(), W::Error> {
194 let _ = FF::write_f64(&mut self.buf, value);
195 self.writer.write_all(&self.buf.as_bytes()).await
196 }
197
198 async fn write_f32(&mut self, value: f32) -> Result<(), W::Error> {
199 let _ = FF::write_f32(&mut self.buf, value);
200 self.writer.write_all(&self.buf.as_bytes()).await
201 }
202}
203
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208 use rstest::*;
209 use std::fmt::Write;
210
211 #[tokio::test]
212 async fn test_json_writer() {
213 _test_json_writer(JsonWriter::new(&mut Vec::new(), CompactFormatter, DefaultFloatFormat)).await;
214 }
215
216 #[tokio::test]
217 async fn test_json_writer_compact() {
218 _test_json_writer(JsonWriter::new_compact(&mut Vec::new())).await;
219 }
220
221 #[tokio::test]
222 async fn test_json_writer_pretty() {
223 _test_json_writer(JsonWriter::new_pretty(&mut Vec::new())).await;
224 }
225
226 async fn _test_json_writer<'a, F: JsonFormatter>(mut writer: JsonWriter<'a, Vec<u8>, F, DefaultFloatFormat>) {
227 writer.write_bytes(b"a").await.unwrap();
228 writer.write_bytes(b"b").await.unwrap();
229 writer.write_bytes(b"cde").await.unwrap();
230
231 assert_eq!(as_written_string(writer), "abcde");
232 }
233
234 fn as_written_string<F: JsonFormatter>(writer: JsonWriter<Vec<u8>, F, DefaultFloatFormat>) -> String {
235 let s = writer.into_inner().unwrap().to_vec();
236 String::from_utf8(s).unwrap()
237 }
238
239 #[rstest]
240 #[case::empty("", r#""""#)]
241 #[case::text("yo", r#""yo""#)]
242 #[case::non_ascii("äöü", r#""äöü""#)]
243 #[case::quotation_mark("\"", r#""\"""#)]
244 #[case::backquote("\\", r#""\\""#)]
245 #[case::backspace("\x08", r#""\b""#)]
246 #[case::form_feed("\x0c", r#""\f""#)]
247 #[case::line_feed("\n", r#""\n""#)]
248 #[case::carriage_return("\r", r#""\r""#)]
249 #[case::tab("\t", r#""\t""#)]
250 #[case::esc_00("\x00", r#""\u0000""#)]
251 #[case::esc_01("\x01", r#""\u0001""#)]
252 #[case::esc_02("\x02", r#""\u0002""#)]
253 #[case::esc_03("\x03", r#""\u0003""#)]
254 #[case::esc_04("\x04", r#""\u0004""#)]
255 #[case::esc_05("\x05", r#""\u0005""#)]
256 #[case::esc_06("\x06", r#""\u0006""#)]
257 #[case::esc_07("\x07", r#""\u0007""#)]
258 #[case::esc_08("\x08", r#""\b""#)]
259 #[case::esc_09("\x09", r#""\t""#)]
260 #[case::esc_0a("\x0a", r#""\n""#)]
261 #[case::esc_0b("\x0b", r#""\u000b""#)]
262 #[case::esc_0c("\x0c", r#""\f""#)]
263 #[case::esc_0d("\x0d", r#""\r""#)]
264 #[case::esc_0e("\x0e", r#""\u000e""#)]
265 #[case::esc_0f("\x0f", r#""\u000f""#)]
266 #[case::esc_10("\x10", r#""\u0010""#)]
267 #[case::esc_11("\x11", r#""\u0011""#)]
268 #[case::esc_12("\x12", r#""\u0012""#)]
269 #[case::esc_13("\x13", r#""\u0013""#)]
270 #[case::esc_14("\x14", r#""\u0014""#)]
271 #[case::esc_15("\x15", r#""\u0015""#)]
272 #[case::esc_16("\x16", r#""\u0016""#)]
273 #[case::esc_17("\x17", r#""\u0017""#)]
274 #[case::esc_18("\x18", r#""\u0018""#)]
275 #[case::esc_19("\x19", r#""\u0019""#)]
276 #[case::esc_1a("\x1a", r#""\u001a""#)]
277 #[case::esc_1b("\x1b", r#""\u001b""#)]
278 #[case::esc_1c("\x1c", r#""\u001c""#)]
279 #[case::esc_1d("\x1d", r#""\u001d""#)]
280 #[case::esc_1e("\x1e", r#""\u001e""#)]
281 #[case::esc_1f("\x1f", r#""\u001f""#)]
282 #[case::combination("asdf \n jklö \t!", r#""asdf \n jklö \t!""#)]
283 #[tokio::test]
284 async fn test_write_escaped_string(#[case] s: &str, #[case] expected: &str) {
285 let mut buf = Vec::new();
286 let mut writer = JsonWriter::new_compact(&mut buf);
287 writer.write_escaped_string(s).await.unwrap();
288 assert_eq!(as_written_string(writer), expected);
289 }
290
291 #[rstest]
292 #[case::bool_true(true, "true")]
293 #[case::bool_false(false, "false")]
294 #[tokio::test]
295 async fn test_write_bool(#[case] b: bool, #[case] expected: &str) {
296 let mut buf = Vec::new();
297 let mut writer = JsonWriter::new_compact(&mut buf);
298 writer.write_bool(b).await.unwrap();
299 assert_eq!(as_written_string(writer), expected);
300 }
301
302 #[rstest]
303 #[case::simple(2.0, "2")]
304 #[case::exp_5(1.234e5, "123400")]
305 #[case::exp_10(1.234e10, "1.234e10")]
306 #[case::exp_20(1.234e20, "1.234e20")]
307 #[case::exp_neg_3(1.234e-3, "0.001234")]
308 #[case::exp_neg_10(1.234e-10, "1.234e-10")]
309 #[case::neg_simple(-2.0, "-2")]
310 #[case::neg_exp_5(-1.234e5, "-123400")]
311 #[case::neg_exp_10(-1.234e10, "-1.234e10")]
312 #[case::neg_exp_20(-1.234e20, "-1.234e20")]
313 #[case::neg_exp_neg_3(-1.234e-3, "-0.001234")]
314 #[case::neg_exp_neg_10(-1.234e-10, "-1.234e-10")]
315 #[case::inf(f64::INFINITY, "null")]
316 #[case::neg_inf(f64::NEG_INFINITY, "null")]
317 #[case::nan(f64::NAN, "null")]
318 #[tokio::test]
319 async fn test_write_f64(#[case] value: f64, #[case] expected: &str) {
320 let mut buf = Vec::new();
321 let mut writer = JsonWriter::new_compact(&mut buf);
322 writer.write_f64(value).await.unwrap();
323 assert_eq!(as_written_string(writer), expected);
324 }
325
326 #[rstest]
327 #[case::simple(2.0, "2")]
328 #[case::exp_5(1.234e5, "123400")]
329 #[case::exp_10(1.234e10, "1.234e10")]
330 #[case::exp_20(1.234e20, "1.234e20")]
331 #[case::exp_neg_3(1.234e-3, "0.001234")]
332 #[case::exp_neg_10(1.234e-10, "1.234e-10")]
333 #[case::neg_simple(-2.0, "-2")]
334 #[case::neg_exp_5(-1.234e5, "-123400")]
335 #[case::neg_exp_10(-1.234e10, "-1.234e10")]
336 #[case::neg_exp_20(-1.234e20, "-1.234e20")]
337 #[case::neg_exp_neg_3(-1.234e-3, "-0.001234")]
338 #[case::neg_exp_neg_10(-1.234e-10, "-1.234e-10")]
339 #[case::inf(f32::INFINITY, "null")]
340 #[case::neg_inf(f32::NEG_INFINITY, "null")]
341 #[case::nan(f32::NAN, "null")]
342 #[tokio::test]
343 async fn test_write_f32(#[case] value: f32, #[case] expected: &str) {
344 let mut buf = Vec::new();
345 let mut writer = JsonWriter::new_compact(&mut buf);
346 writer.write_f32(value).await.unwrap();
347 assert_eq!(as_written_string(writer), expected);
348 }
349
350 #[tokio::test]
351 async fn test_float_format() {
352 struct OtherFf;
353 impl FloatFormat for OtherFf {
354 fn write_f64(f: &mut impl Write, value: f64) -> std::fmt::Result {
355 write!(f, "_{}_64", value)
356 }
357
358 fn write_f32(f: &mut impl Write, value: f32) -> std::fmt::Result {
359 write!(f, "_{}_32", value)
360 }
361 }
362
363 let mut buf = Vec::new();
364 let mut writer = JsonWriter::new(&mut buf, CompactFormatter, OtherFf);
365 writer.write_f64(1.2).await.unwrap();
366 writer.write_f32(3.4).await.unwrap();
367 let written = writer.into_inner().unwrap().to_vec();
368 assert_eq!(&written, b"_1.2_64_3.4_32");
369 }
370}