1use crate::blocking::array::JsonArray;
2use crate::blocking::io::BlockingWrite;
3use crate::blocking::json_writer::JsonWriter;
4use crate::shared::*;
5
6pub struct JsonObject<'a, 'b, W: BlockingWrite, F: JsonFormatter, FF: FloatFormat> {
17 writer: &'a mut JsonWriter<'b, W, F, FF>,
18 is_initial: bool,
19 is_ended: bool,
20}
21impl<'a, 'b, W: BlockingWrite, F: JsonFormatter, FF: FloatFormat> JsonObject<'a, 'b, W, F, FF> {
22 pub fn new(writer: &'a mut JsonWriter<'b, W, F, FF>) -> Result<Self, W::Error> {
25 writer.write_bytes(b"{")?;
26 writer.write_format_after_start_nested()?;
27 Ok(JsonObject {
28 writer,
29 is_initial: true,
30 is_ended: false,
31 })
32 }
33
34 fn write_key(&mut self, key: &str) -> Result<(), W::Error> {
35 if !self.is_initial {
36 self.writer.write_bytes(b",")?;
37 self.writer.write_format_after_element()?;
38 }
39 self.is_initial = false;
40 self.writer.write_format_indent()?;
41 self.writer.write_escaped_string(key)?;
42 self.writer.write_bytes(b":")?;
43 self.writer.write_format_after_key()
44 }
45
46 pub fn write_string_value(&mut self, key: &str, value: &str) -> Result<(), W::Error> {
48 self.write_key(key)?;
49 self.writer.write_escaped_string(value)
50 }
51
52 pub fn write_bool_value(&mut self, key: &str, value: bool) -> Result<(), W::Error> {
54 self.write_key(key)?;
55 self.writer.write_bool(value)
56 }
57
58 pub fn write_null_value(&mut self, key: &str) -> Result<(), W::Error> {
60 self.write_key(key)?;
61 self.writer.write_bytes(b"null")
62 }
63
64 pub fn write_f64_value(&mut self, key: &str, value: f64) -> Result<(), W::Error> {
69 self.write_key(key)?;
70 self.writer.write_f64(value)
71 }
72
73 pub fn write_f32_value(&mut self, key: &str, value: f32) -> Result<(), W::Error> {
78 self.write_key(key)?;
79 self.writer.write_f32(value)
80 }
81
82 pub fn start_object<'c, 'x>(&'x mut self, key: &str) -> Result<JsonObject<'c, 'b, W, F, FF>, W::Error>
87 where 'a: 'c, 'x: 'c
88 {
89 self.write_key(key)?;
90 JsonObject::new(self.writer)
91 }
92
93 pub fn start_array<'c, 'x>(&'x mut self, key: &str) -> Result<JsonArray<'c, 'b, W, F, FF>, W::Error>
98 where 'a: 'c, 'x: 'c
99 {
100 self.write_key(key)?;
101 JsonArray::new(self.writer)
102 }
103
104 pub fn end(self) -> Result<(), W::Error> {
106 let mut mut_self = self;
107 mut_self._end()
108 }
109
110 fn _end(&mut self) -> Result<(), W::Error> {
111 self.writer.write_format_before_end_nested(self.is_initial)?;
112 self.writer.write_bytes(b"}")?;
113 self.is_ended = true;
114 Ok(())
115 }
116}
117
118macro_rules! write_obj_int {
119 ($t:ty ; $f:ident) => {
120impl<'a, 'b, W: BlockingWrite, F: JsonFormatter, FF: FloatFormat> JsonObject<'a, 'b, W, F, FF> {
121 pub fn $f(&mut self, key: &str, value: $t) -> Result<(), W::Error> {
123 self.write_key(key)?;
124 self.writer.write_raw_num(value)
125 }
126}
127 };
128}
129write_obj_int!(i8; write_i8_value);
130write_obj_int!(u8; write_u8_value);
131write_obj_int!(i16; write_i16_value);
132write_obj_int!(u16; write_u16_value);
133write_obj_int!(i32; write_i32_value);
134write_obj_int!(u32; write_u32_value);
135write_obj_int!(i64; write_i64_value);
136write_obj_int!(u64; write_u64_value);
137write_obj_int!(i128; write_i128_value);
138write_obj_int!(u128; write_u128_value);
139write_obj_int!(isize; write_isize_value);
140write_obj_int!(usize; write_usize_value);
141
142impl <'a, 'b, W: BlockingWrite, F: JsonFormatter, FF: FloatFormat> Drop for JsonObject<'a, 'b, W, F, FF> {
143 fn drop(&mut self) {
144 if !self.is_ended {
145 if let Err(e) = self._end() {
146 self.writer.set_unreported_error(e);
147 }
148 }
149 }
150}
151
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156 use rstest::*;
157 use std::io;
158
159 type OS<'a, 'b> = JsonObject<'a, 'b, Vec<u8>, CompactFormatter, DefaultFloatFormat>;
160
161 #[rstest]
162 #[case::empty(Box::new(|_ser: &mut OS| Ok(())), "{}")]
163 #[case::single(Box::new(|ser: &mut OS| ser.write_null_value("a")), r#"{"a":null}"#)]
164 #[case::two(Box::new(|ser: &mut OS| { ser.write_u32_value("a", 1)?; ser.write_u32_value("b", 2) }), r#"{"a":1,"b":2}"#)]
165 #[case::nested_arr(Box::new(|ser: &mut OS| { ser.start_array("x")?.end() }), r#"{"x":[]}"#)]
166 #[case::nested_arr_with_el(Box::new(|ser: &mut OS| { let mut n = ser.start_array("y")?; n.write_u32_value(5) }), r#"{"y":[5]}"#)]
167 #[case::nested_arr_first(Box::new(|ser: &mut OS| { ser.start_array("z")?.end()?; ser.write_u32_value("q", 4) }), r#"{"z":[],"q":4}"#)]
168 #[case::nested_arr_last(Box::new(|ser: &mut OS| { ser.write_u32_value("q", 6)?; ser.start_array("z")?.end() }), r#"{"q":6,"z":[]}"#)]
169 #[case::nested_arr_between(Box::new(|ser: &mut OS| { ser.write_u32_value("a", 7)?; ser.start_array("b")?.end()?; ser.write_u32_value("c", 9) }), r#"{"a":7,"b":[],"c":9}"#)]
170 #[case::two_nested_arrays(Box::new(|ser: &mut OS| { ser.start_array("d")?.end()?; ser.start_array("e")?.end() }), r#"{"d":[],"e":[]}"#)]
171 #[case::nested_obj(Box::new(|ser: &mut OS| { ser.start_object("f")?.end() }), r#"{"f":{}}"#)]
172 #[case::nested_obj_with_el(Box::new(|ser: &mut OS| { let mut n=ser.start_object("g")?; n.write_u32_value("a", 3) }), r#"{"g":{"a":3}}"#)]
173 #[case::nested_obj_first(Box::new(|ser: &mut OS| { ser.start_object("h")?.end()?; ser.write_u32_value("i", 0) }), r#"{"h":{},"i":0}"#)]
174 #[case::nested_obj_last(Box::new(|ser: &mut OS| { ser.write_u32_value("j", 2)?; ser.start_object("k")?.end() }), r#"{"j":2,"k":{}}"#)]
175 #[case::two_nested_objects(Box::new(|ser: &mut OS| { ser.start_object("l")?.end()?; ser.start_object("m")?.end() }), r#"{"l":{},"m":{}}"#)]
176 fn test_object(#[case] code: Box<dyn Fn(&mut OS) -> io::Result<()>>, #[case] expected: &str) -> io::Result<()> {
177 let mut buf = Vec::new();
178 let mut writer = JsonWriter::new_compact(&mut buf);
179 {
180 let mut object_ser = JsonObject::new(&mut writer)?;
181 code(&mut object_ser)?;
182 }
183
184 let actual = String::from_utf8(buf).unwrap();
185 assert_eq!(actual, expected);
186 Ok(())
187 }
188
189 #[rstest]
190 #[case::null(Box::new(|w: &mut OS| w.write_null_value("a")), "null")]
191 #[case::bool_true(Box::new(|w: &mut OS| w.write_bool_value("a", true)), "true")]
192 #[case::bool_false(Box::new(|w: &mut OS| w.write_bool_value("a", false)), "false")]
193 #[case::string(Box::new(|w: &mut OS| w.write_string_value("a", "asdf")), r#""asdf""#)]
194 #[case::string_escaped(Box::new(|w: &mut OS| w.write_string_value("a", "\r\n")), r#""\r\n""#)]
195 #[case::u8(Box::new(|w: &mut OS| w.write_u8_value("a", 2u8)), "2")]
196 #[case::i8(Box::new(|w: &mut OS| w.write_i8_value("a", -3i8)), "-3")]
197 #[case::u16(Box::new(|w: &mut OS| w.write_u16_value("a", 4u16)), "4")]
198 #[case::i16(Box::new(|w: &mut OS| w.write_i16_value("a", -5i16)), "-5")]
199 #[case::u32(Box::new(|w: &mut OS| w.write_u32_value("a", 6u32)), "6")]
200 #[case::i32(Box::new(|w: &mut OS| w.write_i32_value("a", -7i32)), "-7")]
201 #[case::u64(Box::new(|w: &mut OS| w.write_u64_value("a", 8u64)), "8")]
202 #[case::i64(Box::new(|w: &mut OS| w.write_i64_value("a", -9i64)), "-9")]
203 #[case::u128(Box::new(|w: &mut OS| w.write_u128_value("a", 12u128)), "12")]
204 #[case::i128(Box::new(|w: &mut OS| w.write_i128_value("a", -13i128)), "-13")]
205 #[case::usize(Box::new(|w: &mut OS| w.write_usize_value("a", 10usize)), "10")]
206 #[case::isize(Box::new(|w: &mut OS| w.write_isize_value("a", -11isize)), "-11")]
207 #[case::f64(Box::new(|w: &mut OS| w.write_f64_value("a", 2.0)), "2")]
208 #[case::f64_exp_5(Box::new(|w: &mut OS| w.write_f64_value("a", 1.234e5)), "123400")]
209 #[case::f64_exp_10(Box::new(|w: &mut OS| w.write_f64_value("a", 1.234e10)), "1.234e10")]
210 #[case::f64_exp_20(Box::new(|w: &mut OS| w.write_f64_value("a", 1.234e20)), "1.234e20")]
211 #[case::f64_exp_neg_3(Box::new(|w: &mut OS| w.write_f64_value("a", 1.234e-3)), "0.001234")]
212 #[case::f64_exp_neg_10(Box::new(|w: &mut OS| w.write_f64_value("a", 1.234e-10)), "1.234e-10")]
213 #[case::f64_neg(Box::new(|w: &mut OS| w.write_f64_value("a", -2.0)), "-2")]
214 #[case::f64_neg_exp_5(Box::new(|w: &mut OS| w.write_f64_value("a", -1.234e5)), "-123400")]
215 #[case::f64_neg_exp_10(Box::new(|w: &mut OS| w.write_f64_value("a", -1.234e10)), "-1.234e10")]
216 #[case::f64_neg_exp_20(Box::new(|w: &mut OS| w.write_f64_value("a", -1.234e20)), "-1.234e20")]
217 #[case::f64_neg_exp_neg_3(Box::new(|w: &mut OS| w.write_f64_value("a", -1.234e-3)), "-0.001234")]
218 #[case::f64_neg_exp_neg_10(Box::new(|w: &mut OS| w.write_f64_value("a", -1.234e-10)), "-1.234e-10")]
219 #[case::f64_inf(Box::new(|w: &mut OS| w.write_f64_value("a", f64::INFINITY)), "null")]
220 #[case::f64_neg_inf(Box::new(|w: &mut OS| w.write_f64_value("a", f64::NEG_INFINITY)), "null")]
221 #[case::f64_nan(Box::new(|w: &mut OS| w.write_f64_value("a", f64::NAN)), "null")]
222 #[case::f32(Box::new(|w: &mut OS| w.write_f32_value("a", 2.0)), "2")]
223 #[case::f32_exp_5(Box::new(|w: &mut OS| w.write_f32_value("a", 1.234e5)), "123400")]
224 #[case::f32_exp_10(Box::new(|w: &mut OS| w.write_f32_value("a", 1.234e10)), "1.234e10")]
225 #[case::f32_exp_20(Box::new(|w: &mut OS| w.write_f32_value("a", 1.234e20)), "1.234e20")]
226 #[case::f32_exp_neg_3(Box::new(|w: &mut OS| w.write_f32_value("a", 1.234e-3)), "0.001234")]
227 #[case::f32_exp_neg_10(Box::new(|w: &mut OS| w.write_f32_value("a", 1.234e-10)), "1.234e-10")]
228 #[case::f32_neg(Box::new(|w: &mut OS| w.write_f32_value("a", -2.0)), "-2")]
229 #[case::f32_neg_exp_5(Box::new(|w: &mut OS| w.write_f32_value("a", -1.234e5)), "-123400")]
230 #[case::f32_neg_exp_10(Box::new(|w: &mut OS| w.write_f32_value("a", -1.234e10)), "-1.234e10")]
231 #[case::f32_neg_exp_20(Box::new(|w: &mut OS| w.write_f32_value("a", -1.234e20)), "-1.234e20")]
232 #[case::f32_neg_exp_neg_3(Box::new(|w: &mut OS| w.write_f32_value("a", -1.234e-3)), "-0.001234")]
233 #[case::f32_neg_exp_neg_10(Box::new(|w: &mut OS| w.write_f32_value("a", -1.234e-10)), "-1.234e-10")]
234 #[case::f32_inf(Box::new(|w: &mut OS| w.write_f32_value("a", f32::INFINITY)), "null")]
235 #[case::f32_neg_inf(Box::new(|w: &mut OS| w.write_f32_value("a", f32::NEG_INFINITY)), "null")]
236 #[case::f32_nan(Box::new(|w: &mut OS| w.write_f32_value("a", f32::NAN)), "null")]
237 fn test_write_value(#[case] code: Box<dyn Fn(&mut OS) -> io::Result<()>>, #[case] expected: &str) -> io::Result<()> {
238 {
239 let mut buf = Vec::new();
240 let mut writer = JsonWriter::new_compact(&mut buf);
241 {
242 let mut object_ser = JsonObject::new(&mut writer)?;
243 code(&mut object_ser)?;
244 }
245
246 let actual = String::from_utf8(buf).unwrap();
247 let expected = format!(r#"{}"a":{}{}"#, "{", expected, "}");
248 assert_eq!(actual, expected);
249 }
250
251 {
253 let mut buf = Vec::new();
254 let mut writer = JsonWriter::new_compact(&mut buf);
255 {
256 let mut object_ser = JsonObject::new(&mut writer)?;
257 object_ser.write_null_value("x")?;
258 code(&mut object_ser)?;
259 object_ser.write_u32_value("y", 5)?;
260 }
261
262 let actual = String::from_utf8(buf).unwrap();
263 let expected = format!(r#"{}"x":null,"a":{},"y":5{}"#, "{", expected, "}");
264 assert_eq!(actual, expected);
265 }
266
267 Ok(())
268 }
269}