1#![doc = include_str!("../README.md")]
2
3use core::fmt;
4
5pub struct JSONObjectWriter<'a, Writer: JSONWriter = String> {
12 pub writer: &'a mut Writer,
19 empty: bool,
20}
21
22pub struct JSONArrayWriter<'a, Writer: JSONWriter = String> {
29 pub writer: &'a mut Writer,
36 empty: bool,
37}
38
39pub struct JSONStringWriter<'a, Writer: JSONWriter = String> {
41 pub writer: &'a mut Writer,
43}
44
45impl<'a, Writer: JSONWriter> JSONStringWriter<'a, Writer> {
46 #[inline(always)]
48 pub fn new(writer: &mut Writer) -> JSONStringWriter<'_, Writer> {
49 writer.json_begin_string();
50 JSONStringWriter { writer }
51 }
52
53 #[inline(always)]
58 pub fn end(self) {
59 drop(self)
60 }
61}
62
63impl<'a, Writer: JSONWriter> fmt::Write for JSONStringWriter<'a, Writer> {
64 #[inline(always)]
65 fn write_str(&mut self, s: &str) -> fmt::Result {
66 self.writer.json_string_part(s);
67 Ok(())
68 }
69}
70
71impl<Writer: JSONWriter> Drop for JSONStringWriter<'_, Writer> {
72 #[inline(always)]
73 fn drop(&mut self) {
74 self.writer.json_end_string()
75 }
76}
77
78#[doc(hidden)]
79#[derive(Debug, Copy, Clone)]
80pub struct Null();
81
82pub trait JSONWriter {
88 #[inline(always)]
90 fn json_null(&mut self) {
91 self.json_fragment("null");
92 }
93
94 fn json_bool(&mut self, value: bool) {
96 self.json_fragment(if value { "true" } else { "false" });
97 }
98
99 fn json_string(&mut self, value: &str);
101
102 fn json_string_part(&mut self, value: &str);
104
105 #[inline(never)]
107 fn json_number_f64(&mut self, value: f64) {
108 if !value.is_finite() {
109 self.json_null();
111 return;
112 }
113
114 let mut buf = ryu::Buffer::new();
115 let mut result = buf.format_finite(value);
116 if result.ends_with(".0") {
117 result = unsafe { result.get_unchecked(..result.len() - 2) };
118 }
119 self.json_number_str(result);
120 }
121
122 #[inline(always)]
124 fn json_number_str(&mut self, value: &str) {
125 self.json_fragment(value);
126 }
127
128 #[inline(always)]
130 fn json_begin_object(&mut self) {
131 self.json_fragment("{");
132 }
133
134 #[inline(always)]
138 fn json_end_object(&mut self, _empty: bool) {
139 self.json_fragment("}");
140 }
141
142 #[inline(always)]
144 fn json_begin_array(&mut self) {
145 self.json_fragment("[");
146 }
147
148 #[inline(always)]
152 fn json_end_array(&mut self, _empty: bool) {
153 self.json_fragment("]");
154 }
155
156 #[inline(always)]
160 fn json_begin_string(&mut self) {
161 self.json_fragment("\"");
162 }
163
164 #[inline(always)]
168 fn json_end_string(&mut self) {
169 self.json_fragment("\"");
170 }
171
172 #[inline]
175 fn json_begin_array_value(&mut self, first: bool) {
176 if !first {
177 self.json_fragment(",");
178 }
179 }
180
181 fn json_object_key(&mut self, key: &str, first: bool) {
183 if !first {
184 self.json_fragment(",");
185 }
186 self.json_string(key);
187 self.json_fragment(":");
188 }
189
190 fn json_fragment(&mut self, value: &str);
192}
193
194pub static NULL: Null = Null();
200
201impl<W: JSONWriter> JSONObjectWriter<'_, W> {
202 #[inline(always)]
206 pub fn new(writer: &mut W) -> JSONObjectWriter<'_, W> {
207 writer.json_begin_object();
208 JSONObjectWriter {
209 writer,
210 empty: true,
211 }
212 }
213
214 #[inline(always)]
220 pub fn object<'a>(&'a mut self, key: &str) -> JSONObjectWriter<'a, W> {
221 self.write_key(key);
222 JSONObjectWriter::new(self.writer)
223 }
224
225 #[inline(always)]
231 pub fn array<'a>(&'a mut self, key: &str) -> JSONArrayWriter<'a, W> {
232 self.write_key(key);
233 JSONArrayWriter::new(self.writer)
234 }
235
236 #[inline(always)]
240 pub fn value<T: JSONWriterValue>(&mut self, key: &str, value: T) {
241 self.write_key(key);
242 value.write_json(self.writer);
243 }
244
245 #[inline(always)]
248 pub fn string_writer(&mut self, key: &str) -> JSONStringWriter<'_, W> {
249 self.write_key(key);
250 JSONStringWriter::new(self.writer)
251 }
252
253 pub fn write_key(&mut self, key: &str) {
264 self.writer.json_object_key(key, self.empty);
265 self.empty = false;
266 }
267
268 #[inline(always)]
273 pub fn end(self) {
274 drop(self);
275 }
276}
277
278impl JSONObjectWriter<'_, String> {
279 #[inline(always)]
283 pub fn output_buffered_data<Writer: std::io::Write>(
284 &mut self,
285 writer: &mut Writer,
286 ) -> Result<usize, std::io::Error> {
287 output_buffer_to(self.writer, writer)
288 }
289
290 #[inline(always)]
294 pub fn buffer_len(&self) -> usize {
295 self.writer.len()
296 }
297}
298
299impl<'a, W: JSONWriter> Drop for JSONObjectWriter<'a, W> {
300 #[inline(always)]
301 fn drop(&mut self) {
302 self.writer.json_end_object(self.empty);
303 }
304}
305
306impl<W: JSONWriter> JSONArrayWriter<'_, W> {
307 #[inline(always)]
311 pub fn new(writer: &mut W) -> JSONArrayWriter<'_, W> {
312 writer.json_begin_array();
313 JSONArrayWriter {
314 writer,
315 empty: true,
316 }
317 }
318
319 #[inline(always)]
325 pub fn object(&mut self) -> JSONObjectWriter<'_, W> {
326 self.write_comma();
327 JSONObjectWriter::new(self.writer)
328 }
329
330 #[inline(always)]
336 pub fn array(&mut self) -> JSONArrayWriter<'_, W> {
337 self.write_comma();
338 JSONArrayWriter::new(self.writer)
339 }
340
341 #[inline(always)]
345 pub fn value<T: JSONWriterValue>(&mut self, value: T) {
346 self.write_comma();
347 value.write_json(self.writer);
348 }
349
350 #[inline(always)]
353 pub fn string_writer(&mut self) -> JSONStringWriter<'_, W> {
354 self.write_comma();
355 JSONStringWriter::new(self.writer)
356 }
357
358 #[inline]
367 pub fn write_comma(&mut self) {
368 self.writer.json_begin_array_value(self.empty);
369 self.empty = false;
370 }
371
372 #[inline(always)]
377 pub fn end(self) {
378 drop(self);
379 }
380}
381
382impl<W: JSONWriter> Drop for JSONArrayWriter<'_, W> {
383 #[inline(always)]
384 fn drop(&mut self) {
385 self.writer.json_end_array(self.empty);
386 }
387}
388
389impl JSONArrayWriter<'_, String> {
390 #[inline(always)]
394 pub fn output_buffered_data<Writer: std::io::Write>(
395 &mut self,
396 writer: &mut Writer,
397 ) -> Result<usize, std::io::Error> {
398 output_buffer_to(self.writer, writer)
399 }
400
401 #[inline(always)]
405 pub fn buffer_len(&self) -> usize {
406 self.writer.len()
407 }
408}
409
410impl JSONWriter for String {
411 #[inline(always)]
412 fn json_string(&mut self, value: &str) {
413 write_string(self, value);
414 }
415
416 #[inline(always)]
417 fn json_string_part(&mut self, value: &str) {
418 write_part_of_string(self, value);
419 }
420
421 #[inline(always)]
422 fn json_fragment(&mut self, value: &str) {
423 self.push_str(value);
424 }
425
426 #[inline(always)]
428 fn json_begin_object(&mut self) {
429 self.push('{');
430 }
431
432 #[inline(always)]
436 fn json_end_object(&mut self, _empty: bool) {
437 self.push('}');
438 }
439
440 #[inline(always)]
442 fn json_begin_array(&mut self) {
443 self.push('[');
444 }
445
446 #[inline(always)]
450 fn json_end_array(&mut self, _empty: bool) {
451 self.push(']');
452 }
453
454 #[inline]
457 fn json_begin_array_value(&mut self, first: bool) {
458 if !first {
459 self.push(',');
460 }
461 }
462
463 fn json_object_key(&mut self, key: &str, first: bool) {
466 if !first {
467 self.push(',');
468 }
469 write_string(self, key);
470 self.push(':');
471 }
472
473 #[inline(always)]
474 fn json_begin_string(&mut self) {
475 self.push('"');
476 }
477
478 #[inline(always)]
479 fn json_end_string(&mut self) {
480 self.push('"');
481 }
482}
483
484pub struct PrettyJSONWriter<'a> {
486 pub buffer: &'a mut String,
488 indent: &'a str,
489 depth: usize,
490}
491
492impl PrettyJSONWriter<'_> {
493 pub fn new(buffer: &mut String) -> PrettyJSONWriter<'_> {
495 PrettyJSONWriter {
497 buffer,
498 indent: " ",
499 depth: 0,
500 }
501 }
502
503 pub fn with_indent<'a>(buffer: &'a mut String, indent: &'a str) -> PrettyJSONWriter<'a> {
505 PrettyJSONWriter {
506 buffer,
507 indent,
508 depth: 0,
509 }
510 }
511
512 fn write_indent(&mut self) {
513 for _ in 0..self.depth {
514 self.buffer.push_str(self.indent);
515 }
516 }
517}
518
519impl JSONWriter for PrettyJSONWriter<'_> {
520 fn json_begin_object(&mut self) {
521 self.depth += 1;
522 self.buffer.push('{');
523 }
524
525 fn json_end_object(&mut self, empty: bool) {
526 self.depth -= 1;
527 if !empty {
528 self.buffer.push('\n');
529 self.write_indent();
530 }
531 self.buffer.push('}');
532 }
533
534 fn json_begin_array(&mut self) {
535 self.depth += 1;
536 self.buffer.push('[');
537 }
538
539 fn json_end_array(&mut self, empty: bool) {
540 self.depth -= 1;
541 if !empty {
542 self.buffer.push('\n');
543 self.write_indent();
544 }
545 self.buffer.push(']');
546 }
547
548 fn json_begin_array_value(&mut self, first: bool) {
549 self.buffer.push_str(if first { "\n" } else { ",\n" });
550 self.write_indent();
551 }
552
553 fn json_object_key(&mut self, key: &str, first: bool) {
554 self.buffer.push_str(if first { "\n" } else { ",\n" });
555 self.write_indent();
556 write_string(self.buffer, key);
557 self.buffer.push_str(": ");
558 }
559
560 fn json_string(&mut self, value: &str) {
561 write_string(self.buffer, value);
562 }
563
564 fn json_string_part(&mut self, value: &str) {
565 write_part_of_string(self.buffer, value);
566 }
567
568 fn json_fragment(&mut self, value: &str) {
569 self.buffer.push_str(value);
570 }
571}
572
573pub trait JSONWriterValue {
577 fn write_json<W: JSONWriter>(self, writer: &mut W);
581}
582
583impl JSONWriterValue for &str {
584 #[inline(always)]
585 fn write_json<W: JSONWriter>(self, writer: &mut W) {
586 writer.json_string(self);
587 }
588}
589
590impl JSONWriterValue for &std::borrow::Cow<'_, str> {
591 #[inline(always)]
592 fn write_json<W: JSONWriter>(self, writer: &mut W) {
593 writer.json_string(AsRef::as_ref(self));
594 }
595}
596
597impl JSONWriterValue for &String {
598 #[inline(always)]
599 fn write_json<W: JSONWriter>(self, writer: &mut W) {
600 writer.json_string(self);
601 }
602}
603
604impl JSONWriterValue for f64 {
605 #[inline(always)]
606 fn write_json<W: JSONWriter>(self, writer: &mut W) {
607 writer.json_number_f64(self);
608 }
609}
610
611impl JSONWriterValue for f32 {
612 #[inline(always)]
613 fn write_json<W: JSONWriter>(self, writer: &mut W) {
614 writer.json_number_f64(self as f64);
615 }
616}
617
618impl JSONWriterValue for u128 {
619 #[inline(always)]
620 fn write_json<W: JSONWriter>(self, writer: &mut W) {
621 let mut buf = itoa::Buffer::new();
622 writer.json_number_str(buf.format(self));
623 }
624}
625
626impl JSONWriterValue for i128 {
627 #[inline(always)]
628 fn write_json<W: JSONWriter>(self, writer: &mut W) {
629 let mut buf = itoa::Buffer::new();
630 writer.json_number_str(buf.format(self));
631 }
632}
633
634impl JSONWriterValue for u64 {
635 #[inline(always)]
636 fn write_json<W: JSONWriter>(self, writer: &mut W) {
637 let mut buf = itoa::Buffer::new();
638 writer.json_number_str(buf.format(self));
639 }
640}
641
642impl JSONWriterValue for i64 {
643 #[inline(always)]
644 fn write_json<W: JSONWriter>(self, writer: &mut W) {
645 let mut buf = itoa::Buffer::new();
646 writer.json_number_str(buf.format(self));
647 }
648}
649
650impl JSONWriterValue for u32 {
651 #[inline(always)]
652 fn write_json<W: JSONWriter>(self, writer: &mut W) {
653 let mut buf = itoa::Buffer::new();
654 writer.json_number_str(buf.format(self));
655 }
656}
657
658impl JSONWriterValue for i32 {
659 #[inline(always)]
660 fn write_json<W: JSONWriter>(self, writer: &mut W) {
661 let mut buf = itoa::Buffer::new();
662 writer.json_number_str(buf.format(self));
663 }
664}
665
666impl JSONWriterValue for u16 {
667 #[inline(always)]
668 fn write_json<W: JSONWriter>(self, writer: &mut W) {
669 let mut buf = itoa::Buffer::new();
670 writer.json_number_str(buf.format(self));
671 }
672}
673
674impl JSONWriterValue for i16 {
675 #[inline(always)]
676 fn write_json<W: JSONWriter>(self, writer: &mut W) {
677 let mut buf = itoa::Buffer::new();
678 writer.json_number_str(buf.format(self));
679 }
680}
681
682impl JSONWriterValue for u8 {
683 #[inline(always)]
684 fn write_json<W: JSONWriter>(self, writer: &mut W) {
685 let mut buf = itoa::Buffer::new();
686 writer.json_number_str(buf.format(self));
687 }
688}
689
690impl JSONWriterValue for i8 {
691 #[inline(always)]
692 fn write_json<W: JSONWriter>(self, writer: &mut W) {
693 let mut buf = itoa::Buffer::new();
694 writer.json_number_str(buf.format(self));
695 }
696}
697
698impl JSONWriterValue for bool {
699 #[inline(always)]
700 fn write_json<W: JSONWriter>(self, writer: &mut W) {
701 writer.json_bool(self);
702 }
703}
704
705impl JSONWriterValue for Null {
706 #[inline(always)]
707 fn write_json<W: JSONWriter>(self, writer: &mut W) {
708 writer.json_null();
709 }
710}
711
712impl<T: JSONWriterValue + Copy> JSONWriterValue for &T {
713 #[inline(always)]
714 fn write_json<W: JSONWriter>(self, writer: &mut W) {
715 (*self).write_json(writer);
716 }
717}
718
719impl<T: JSONWriterValue> JSONWriterValue for Option<T> {
720 #[inline]
721 fn write_json<W: JSONWriter>(self, writer: &mut W) {
722 match self {
723 None => {
724 writer.json_null();
725 }
726 Some(value) => {
727 value.write_json(writer);
728 }
729 }
730 }
731}
732
733impl<Item> JSONWriterValue for &Vec<Item>
734where
735 for<'b> &'b Item: JSONWriterValue,
736{
737 #[inline(always)]
738 fn write_json<W: JSONWriter>(self, writer: &mut W) {
739 self.as_slice().write_json(writer);
740 }
741}
742
743impl<Item> JSONWriterValue for &[Item]
744where
745 for<'b> &'b Item: JSONWriterValue,
746{
747 fn write_json<W: JSONWriter>(self, writer: &mut W) {
748 let mut array = JSONArrayWriter::new(writer);
749 for item in self.iter() {
750 array.value(item);
751 }
752 }
753}
754
755impl<Key: AsRef<str>, Item> JSONWriterValue for &std::collections::HashMap<Key, Item>
756where
757 for<'b> &'b Item: JSONWriterValue,
758{
759 fn write_json<W: JSONWriter>(self, writer: &mut W) {
760 let mut obj = JSONObjectWriter::new(writer);
761 for (key, value) in self.iter() {
762 obj.value(key.as_ref(), value);
763 }
764 }
765}
766
767impl<Key: AsRef<str>, Item> JSONWriterValue for &std::collections::BTreeMap<Key, Item>
768where
769 for<'b> &'b Item: JSONWriterValue,
770{
771 fn write_json<W: JSONWriter>(self, writer: &mut W) {
772 let mut obj = JSONObjectWriter::new(writer);
773 for (key, value) in self.iter() {
774 obj.value(key.as_ref(), value);
775 }
776 }
777}
778
779#[inline]
783pub fn to_json_string<T: JSONWriterValue>(v: T) -> String {
784 let mut result = String::new();
785 v.write_json(&mut result);
786 return result;
787}
788
789fn output_buffer_to<Writer: std::io::Write>(
790 buffer: &mut String,
791 writer: &mut Writer,
792) -> Result<usize, std::io::Error> {
793 match writer.write_all(buffer.as_bytes()) {
794 Ok(_) => {
795 let len = buffer.len();
796 buffer.clear();
797 Ok(len)
798 }
799 Err(err) => Err(err),
800 }
801}
802
803#[inline(never)]
807pub fn write_string(output_buffer: &mut String, input: &str) {
808 output_buffer.push('"');
809 write_part_of_string_impl(output_buffer, input);
810 output_buffer.push('"');
811}
812
813#[inline(never)]
817pub fn write_part_of_string(output_buffer: &mut String, input: &str) {
818 write_part_of_string_impl(output_buffer, input);
819}
820
821const fn get_replacements() -> [u8; 256] {
822 let mut result = [0u8; 256];
827 let mut i = 0;
829 while i < 0x20 {
830 result[i] = b'u';
831 i += 1;
832 }
833 result[b'\"' as usize] = b'"';
834 result[b'\\' as usize] = b'\\';
835 result[b'/' as usize] = b'/';
836 result[8] = b'b';
837 result[0xc] = b'f';
838 result[b'\n' as usize] = b'n';
839 result[b'\r' as usize] = b'r';
840 result[b'\t' as usize] = b't';
841 result[0] = b'u';
842
843 return result;
844}
845
846static REPLACEMENTS: [u8; 256] = get_replacements();
847static HEX: [u8; 16] = *b"0123456789ABCDEF";
848
849#[inline(always)]
853fn write_part_of_string_impl(output_buffer: &mut String, input: &str) {
854 let mut num_bytes_written: usize = 0;
857 let mut index: usize = 0;
858 let bytes = input.as_bytes();
859 while index < bytes.len() {
860 let cur_byte = bytes[index];
861 let replacement = REPLACEMENTS[cur_byte as usize];
862 if replacement != 0 {
863 if num_bytes_written < index {
864 output_buffer.push_str(unsafe { input.get_unchecked(num_bytes_written..index) });
869 }
870 if replacement == b'u' {
871 let bytes: [u8; 6] = [
872 b'\\',
873 b'u',
874 b'0',
875 b'0',
876 HEX[((cur_byte / 16) & 0xF) as usize],
877 HEX[(cur_byte & 0xF) as usize],
878 ];
879 output_buffer.push_str(unsafe { std::str::from_utf8_unchecked(&bytes) });
881 } else {
882 let bytes: [u8; 2] = [b'\\', replacement];
883 output_buffer.push_str(unsafe { std::str::from_utf8_unchecked(&bytes) });
885 }
886 num_bytes_written = index + 1;
887 }
888 index += 1;
889 }
890 if num_bytes_written < bytes.len() {
891 output_buffer.push_str(unsafe { input.get_unchecked(num_bytes_written..bytes.len()) });
895 }
896}
897
898#[cfg(test)]
899mod tests {
900 use super::*;
901
902 #[test]
903 fn test_array() {
904 let mut buffer = String::new();
905 let mut array = JSONArrayWriter::new(&mut buffer);
906 array.value(0u8);
907 array.value(1i32);
908 array.value("2");
909 array.value("\"<script>1/2</script>\"");
910 let mut nested_arr = array.array();
911 nested_arr.value("nested");
912 nested_arr.end();
913 let mut nested_obj = array.object();
914 nested_obj.value("ä\töü", "ä\töü");
915 nested_obj.end();
916 let nested_obj2 = array.object();
917 nested_obj2.end();
918 drop(array);
919
920 assert_eq!(buffer, "[0,1,\"2\",\"\\\"<script>1\\/2<\\/script>\\\"\",[\"nested\"],{\"ä\\töü\":\"ä\\töü\"},{}]");
921 }
922
923 #[test]
924 fn test_array_range() {
925 let bytes = b"ABC";
926 assert_eq!(to_json_string(&bytes[..]), "[65,66,67]");
927
928 let mut v = Vec::<u8>::new();
929 v.extend_from_slice(bytes);
930 assert_eq!(to_json_string(&v), "[65,66,67]");
931 }
932
933 #[test]
934 fn test_object() {
935 let mut map = std::collections::HashMap::<String, String>::new();
936 map.insert("a".to_owned(), "a".to_owned());
937 assert_eq!(to_json_string(&map), "{\"a\":\"a\"}");
938 }
939
940 #[allow(clippy::approx_constant)]
941 #[test]
942 fn test_numbers() {
943 assert_eq!(to_json_string(1u8), "1");
945 assert_eq!(to_json_string(1u16), "1");
946 assert_eq!(to_json_string(1u32), "1");
947 assert_eq!(to_json_string(u8::MAX), "255");
948 assert_eq!(to_json_string(u16::MAX), "65535");
949 assert_eq!(to_json_string(u32::MAX), "4294967295");
950 assert_eq!(to_json_string(u64::MAX), "18446744073709551615");
951 assert_eq!(
952 to_json_string(u128::MAX),
953 "340282366920938463463374607431768211455"
954 );
955
956 assert_eq!(to_json_string(-1i8), "-1");
958 assert_eq!(to_json_string(-1i16), "-1");
959 assert_eq!(to_json_string(-1i32), "-1");
960 assert_eq!(to_json_string(-1i64), "-1");
961 assert_eq!(to_json_string(-1i128), "-1");
962
963 assert_eq!(to_json_string(0f32), "0");
965 assert_eq!(to_json_string(2f32), "2");
966 assert_eq!(to_json_string(-2f32), "-2");
967
968 assert_eq!(to_json_string(0f64), "0");
969 assert_eq!(to_json_string(2f64), "2");
970 assert_eq!(to_json_string(-2f64), "-2");
971 assert_eq!(to_json_string(3.141592653589793), "3.141592653589793");
972 assert_eq!(to_json_string(0.1f64), "0.1");
973 assert_eq!(to_json_string(-0.1f64), "-0.1");
974 assert_eq!(to_json_string(1.5e30f64), "1.5e30");
976 assert_eq!(
977 to_json_string(-2.220446049250313e-16f64),
978 "-2.220446049250313e-16"
979 );
980
981 assert_eq!(to_json_string(1.0 / 0.0), "null");
982 assert_eq!(to_json_string(f64::INFINITY), "null");
983 assert_eq!(to_json_string(f64::NEG_INFINITY), "null");
984 assert_eq!(to_json_string(f64::NAN), "null");
985 }
986
987 #[test]
988 fn test_dtoa() {
989 assert_dtoa(0.0);
990 assert_dtoa(1.0);
991 assert_dtoa(-1.0);
992 assert_dtoa(2.0);
993 }
995
996 fn assert_dtoa(v: f64) {
997 let a = v.to_string();
998 let mut b = String::new();
999 b.json_number_f64(v);
1000 assert_eq!(b, a);
1001 }
1002
1003 #[test]
1004 fn test_strings() {
1005 assert_eq!(
1006 to_json_string("中文\0\x08\x09\"\\\n\r\t</script>"),
1007 "\"中文\\u0000\\b\\t\\\"\\\\\\n\\r\\t<\\/script>\""
1008 );
1009 }
1010
1011 #[test]
1012 fn test_basic_example() {
1013 let mut object_str = String::new();
1014 {
1015 let mut object_writer = JSONObjectWriter::new(&mut object_str);
1016 object_writer.value("number", 42i32);
1017 }
1018 assert_eq!(&object_str, "{\"number\":42}");
1019 }
1020
1021 #[allow(clippy::approx_constant)]
1022 #[test]
1023 fn test_misc_examples() {
1024 assert_eq!(to_json_string("Hello World\n"), "\"Hello World\\n\"");
1026 assert_eq!(to_json_string(3.141592653589793f64), "3.141592653589793");
1027 assert_eq!(to_json_string(true), "true");
1028 assert_eq!(to_json_string(false), "false");
1029 assert_eq!(to_json_string(NULL), "null");
1030
1031 assert_eq!(to_json_string(Option::<u8>::Some(42)), "42");
1033 assert_eq!(to_json_string(Option::<u8>::None), "null");
1034
1035 let numbers: [u8; 4] = [1, 2, 3, 4];
1037 assert_eq!(to_json_string(&numbers[..]), "[1,2,3,4]");
1038 let numbers_vec: Vec<u8> = vec![1u8, 2u8, 3u8, 4u8];
1039 assert_eq!(to_json_string(&numbers_vec), "[1,2,3,4]");
1040 let strings: [&str; 4] = ["a", "b", "c", "d"];
1041 assert_eq!(to_json_string(&strings[..]), "[\"a\",\"b\",\"c\",\"d\"]");
1042
1043 let mut map = std::collections::HashMap::<String, String>::new();
1045 map.insert("Hello".to_owned(), "World".to_owned());
1046 assert_eq!(to_json_string(&map), "{\"Hello\":\"World\"}");
1047
1048 let mut object_str = String::new();
1050 let mut object_writer = JSONObjectWriter::new(&mut object_str);
1051
1052 object_writer.value("number", 42i32);
1054 object_writer.value("slice", &numbers[..]);
1055
1056 let mut nested_array = object_writer.array("array");
1058 nested_array.value(42u32);
1059 nested_array.value("?");
1060 nested_array.end();
1061
1062 let nested_object = object_writer.object("object");
1064 nested_object.end();
1065
1066 object_writer.end();
1067 assert_eq!(
1068 &object_str,
1069 "{\"number\":42,\"slice\":[1,2,3,4],\"array\":[42,\"?\"],\"object\":{}}"
1070 );
1071 }
1072
1073 #[test]
1074 fn test_string_writer() {
1075 use core::fmt::Write;
1076
1077 let mut object_str = String::new();
1078 let mut object_writer = JSONObjectWriter::new(&mut object_str);
1079
1080 let name = r#"zenora "bariella""#;
1081 let color = "yellow";
1082 object_writer.value("name", name);
1083 let mut w = object_writer.string_writer("compound");
1084 write!(w, "{name} : {color}").unwrap();
1085 w.end();
1086
1087 object_writer.value("number", 42i32);
1088
1089 {
1090 let mut array = object_writer.array("tools");
1091 let prefix = "air";
1092 array.value("hammer");
1093 write!(array.string_writer(), "{prefix}-hammer").unwrap();
1094 write!(array.string_writer(), "{prefix}-saw").unwrap();
1095 }
1096
1097 object_writer.end();
1098
1099 eprintln!("{}", object_str);
1100
1101 assert_eq!(
1102 &object_str,
1103 r#"{"name":"zenora \"bariella\"","compound":"zenora \"bariella\" : yellow","number":42,"tools":["hammer","air-hammer","air-saw"]}"#
1104 )
1105 }
1106
1107 #[test]
1108 fn test_duplicate_keys() {
1109 let mut object_str = String::new();
1110 {
1111 let mut object_writer = JSONObjectWriter::new(&mut object_str);
1112 object_writer.value("number", 42i32);
1113 object_writer.value("number", 43i32);
1114 }
1115 assert_eq!(&object_str, "{\"number\":42,\"number\":43}");
1117 }
1118
1119 #[test]
1120 fn test_flush() {
1121 let mut writer = Vec::<u8>::new();
1123
1124 let mut buffer = String::new();
1125 let mut array = JSONArrayWriter::new(&mut buffer);
1126 for i in 1i32..=1000000i32 {
1127 array.value(i);
1128 if array.buffer_len() > 2000 {
1129 array.output_buffered_data(&mut writer).unwrap();
1130 }
1131 }
1132 array.end();
1133 std::io::Write::write_all(&mut writer, buffer.as_bytes()).unwrap();
1134
1135 assert!(buffer.len() <= 4000, "Buffer too long");
1136 assert_eq!(
1137 &writer[writer.len() - b",999999,1000000]".len()..],
1138 b",999999,1000000]"
1139 );
1140 }
1141
1142 #[test]
1143 fn test_encoding() {
1144 for c in 0x00..0x20 {
1145 let c = char::from(c);
1146 let json = to_json_string(c.to_string().as_str());
1147 assert!(&json[0..2] == "\"\\");
1148 }
1149 assert_eq!(
1150 to_json_string("</script >\0\x1F"),
1151 "\"<\\/script >\\u0000\\u001F\""
1152 );
1153 }
1154
1155 #[test]
1156 fn test_pretty() {
1157 let mut buffer = String::new();
1158 let mut formatter = PrettyJSONWriter::with_indent(&mut buffer, " ");
1159 let mut writer = JSONObjectWriter::new(&mut formatter);
1160 {
1161 let mut nested_writer = writer.object("nested");
1162 nested_writer.value("a", 3);
1163 nested_writer.value("b", &vec![0, 1, 4]);
1164 }
1165 writer.value("c", &vec![true, false, true]);
1166 writer.value("d", NULL);
1167 writer.object("e");
1169 writer.array("f");
1170 writer.end();
1171 assert_eq!(
1172 formatter.buffer,
1173 r#"{
1174 "nested": {
1175 "a": 3,
1176 "b": [
1177 0,
1178 1,
1179 4
1180 ]
1181 },
1182 "c": [
1183 true,
1184 false,
1185 true
1186 ],
1187 "d": null,
1188 "e": {},
1189 "f": []
1190}"#
1191 );
1192 }
1193}