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