1use crate::nonblocking::io::NonBlockingWrite;
2use crate::nonblocking::json_writer::JsonWriter;
3use crate::nonblocking::object::JsonObject;
4use crate::shared::*;
5
6pub struct JsonArray<'a, 'b, W: NonBlockingWrite, F: JsonFormatter, FF: FloatFormat> {
17 writer: &'a mut JsonWriter<'b, W, F, FF>,
18 is_initial: bool,
19 is_ended: bool,
20}
21
22impl<'a, 'b, W: NonBlockingWrite, F: JsonFormatter, FF: FloatFormat> JsonArray<'a, 'b, W, F, FF> {
23 pub async fn new(writer: &'a mut JsonWriter<'b, W, F, FF>) -> Result<Self, W::Error> {
26 writer.write_bytes(b"[").await?;
27 writer.write_format_after_start_nested().await?;
28
29 Ok(JsonArray {
30 writer,
31 is_initial: true,
32 is_ended: false,
33 })
34 }
35
36 async fn handle_initial(&mut self) -> Result<(), W::Error> {
37 if self.is_initial {
38 self.is_initial = false;
39 }
40 else {
41 self.writer.write_bytes(b",").await?;
42 self.writer.write_format_after_element().await?;
43 }
44 self.writer.write_format_indent().await?;
45 Ok(())
46 }
47
48 pub async fn unchecked_write_raw_value(&mut self, value_json: &str) -> Result<(), W::Error> {
54 self.handle_initial().await?;
55 self.writer.write_bytes(value_json.as_bytes()).await
56 }
57
58 pub async fn write_string_value(&mut self, value: &str) -> Result<(), W::Error> {
60 self.handle_initial().await?;
61 self.writer.write_escaped_string(value).await
62 }
63
64 pub async fn write_bool_value(&mut self, value: bool) -> Result<(), W::Error> {
66 self.handle_initial().await?;
67 self.writer.write_bool(value).await
68 }
69
70 pub async fn write_null_value(&mut self) -> Result<(), W::Error> {
72 self.handle_initial().await?;
73 self.writer.write_bytes(b"null").await
74 }
75
76 pub async fn write_f64_value(&mut self, value: f64) -> Result<(), W::Error> {
81 self.handle_initial().await?;
82 self.writer.write_f64(value).await
83 }
84
85 pub async fn write_f32_value(&mut self, value: f32) -> Result<(), W::Error> {
90 self.handle_initial().await?;
91 self.writer.write_f32(value).await
92 }
93
94 pub async fn start_object<'c, 'x>(&'x mut self) -> Result<JsonObject<'c, 'b, W, F, FF>, W::Error>
99 where 'a: 'c, 'x: 'c
100 {
101 self.handle_initial().await?;
102 JsonObject::new(self.writer).await
103 }
104
105 pub async fn start_array<'c, 'x>(&'x mut self) -> Result<JsonArray<'c, 'b, W, F, FF>, W::Error>
110 where 'a: 'c, 'x: 'c
111 {
112 self.handle_initial().await?;
113 JsonArray::new(self.writer).await
114 }
115
116 pub async fn end(self) -> Result<(), W::Error> {
118 let mut mut_self = self;
119 mut_self._end().await
120 }
121
122 async fn _end(&mut self) -> Result<(), W::Error> {
123 self.writer.write_format_before_end_nested(self.is_initial).await?;
124 self.writer.write_bytes(b"]").await?;
125 self.is_ended = true;
126 Ok(())
127 }
128}
129
130macro_rules! write_arr_int {
131 ($t:ty ; $f:ident) => {
132impl<'a, 'b, W: NonBlockingWrite, F: JsonFormatter, FF: FloatFormat> JsonArray<'a, 'b, W, F, FF> {
133 pub async fn $f(&mut self, value: $t) -> Result<(), W::Error> {
136 self.handle_initial().await?;
137 self.writer.write_raw_num(value).await
138 }
139}
140 };
141}
142write_arr_int!(i8; write_i8_value);
143write_arr_int!(u8; write_u8_value);
144write_arr_int!(i16; write_i16_value);
145write_arr_int!(u16; write_u16_value);
146write_arr_int!(i32; write_i32_value);
147write_arr_int!(u32; write_u32_value);
148write_arr_int!(i64; write_i64_value);
149write_arr_int!(u64; write_u64_value);
150write_arr_int!(i128; write_i128_value);
151write_arr_int!(u128; write_u128_value);
152write_arr_int!(isize; write_isize_value);
153write_arr_int!(usize; write_usize_value);
154
155
156
157
158#[cfg(test)]
159pub mod tests {
160 use super::*;
161 use crate::nonblocking::object::tests::ObjectCommand;
162 use rstest::*;
163 use std::io;
164
165 pub enum ArrayCommand {
166 Null,
167 Bool(bool),
168 Raw(&'static str),
169 String(&'static str),
170 U8(u8),
171 I8(i8),
172 U16(u16),
173 I16(i16),
174 U32(u32),
175 I32(i32),
176 U64(u64),
177 I64(i64),
178 U128(u128),
179 I128(i128),
180 Usize(usize),
181 Isize(isize),
182 F64(f64),
183 F32(f32),
184 Object(Vec<ObjectCommand>),
185 Array(Vec<ArrayCommand>)
186 }
187 impl ArrayCommand {
188 pub async fn apply(&self, arr: &mut JsonArray<'_, '_, Vec<u8>, CompactFormatter, DefaultFloatFormat>) {
189 match self {
190 ArrayCommand::Null => arr.write_null_value().await.unwrap(),
191 ArrayCommand::Bool(b) => arr.write_bool_value(*b).await.unwrap(),
192 ArrayCommand::Raw(s) => arr.unchecked_write_raw_value(s).await.unwrap(),
193 ArrayCommand::String(s) => arr.write_string_value(s).await.unwrap(),
194 ArrayCommand::U8(n) => arr.write_u8_value(*n).await.unwrap(),
195 ArrayCommand::I8(n) => arr.write_i8_value(*n).await.unwrap(),
196 ArrayCommand::U16(n) => arr.write_u16_value(*n).await.unwrap(),
197 ArrayCommand::I16(n) => arr.write_i16_value(*n).await.unwrap(),
198 ArrayCommand::U32(n) => arr.write_u32_value(*n).await.unwrap(),
199 ArrayCommand::I32(n) => arr.write_i32_value(*n).await.unwrap(),
200 ArrayCommand::U64(n) => arr.write_u64_value(*n).await.unwrap(),
201 ArrayCommand::I64(n) => arr.write_i64_value(*n).await.unwrap(),
202 ArrayCommand::U128(n) => arr.write_u128_value(*n).await.unwrap(),
203 ArrayCommand::I128(n) => arr.write_i128_value(*n).await.unwrap(),
204 ArrayCommand::Usize(n) => arr.write_usize_value(*n).await.unwrap(),
205 ArrayCommand::Isize(n) => arr.write_isize_value(*n).await.unwrap(),
206 ArrayCommand::F64(x) => arr.write_f64_value(*x).await.unwrap(),
207 ArrayCommand::F32(x) => arr.write_f32_value(*x).await.unwrap(),
208 ArrayCommand::Object(cmds) => {
209 let mut nested = arr.start_object().await.unwrap();
210 for cmd in cmds {
211 Box::pin(cmd.apply(&mut nested)).await;
212 }
213 nested.end().await.unwrap();
214 }
215 ArrayCommand::Array(cmds) => {
216 let mut nested = arr.start_array().await.unwrap();
217 for cmd in cmds {
218 Box::pin(cmd.apply(&mut nested)).await;
219 }
220 nested.end().await.unwrap();
221 }
222 }
223 }
224 }
225
226 #[rstest]
227 #[case::empty(vec![], "[]")]
228 #[case::single(vec![ArrayCommand::Null], "[null]")]
229 #[case::two(vec![ArrayCommand::U32(1), ArrayCommand::U32(2)], "[1,2]")]
230 #[case::nested_arr(vec![ArrayCommand::Array(vec![])], "[[]]")]
231 #[case::nested_arr_with_el(vec![ArrayCommand::Array(vec![ArrayCommand::U32(5)])], "[[5]]")]
232 #[case::nested_arr_first(vec![ArrayCommand::Array(vec![]), ArrayCommand::U32(4)], "[[],4]")]
233 #[case::nested_arr_last(vec![ArrayCommand::U32(6), ArrayCommand::Array(vec![])], "[6,[]]")]
234 #[case::nested_arr_between(vec![ArrayCommand::U32(7), ArrayCommand::Array(vec![]), ArrayCommand::U32(9)], "[7,[],9]")]
235 #[case::two_nested_arrays(vec![ArrayCommand::Array(vec![]), ArrayCommand::Array(vec![])], "[[],[]]")]
236 #[case::nested_obj(vec![ArrayCommand::Object(vec![])], "[{}]")]
237 #[case::nested_obj_with_el(vec![ArrayCommand::Object(vec![ObjectCommand::U32("a", 3)])], r#"[{"a":3}]"#)]
238 #[case::nested_obj_first(vec![ArrayCommand::Object(vec![]), ArrayCommand::U32(0)], r#"[{},0]"#)]
239 #[case::nested_obj_last(vec![ArrayCommand::U32(2), ArrayCommand::Object(vec![])], r#"[2,{}]"#)]
240 #[case::two_nested_objects(vec![ArrayCommand::Object(vec![]), ArrayCommand::Object(vec![])], r#"[{},{}]"#)]
241 #[tokio::test]
242 async fn test_array(#[case] code: Vec<ArrayCommand>, #[case] expected: &str) -> io::Result<()> {
243 let mut buf = Vec::new();
244 let mut writer = JsonWriter::new_compact(&mut buf);
245 let mut array_ser = JsonArray::new(&mut writer).await?;
246 for cmd in code {
247 cmd.apply(&mut array_ser).await;
248 }
249 array_ser.end().await?;
250
251 let actual = String::from_utf8(buf).unwrap();
252 assert_eq!(actual, expected);
253 Ok(())
254 }
255
256 #[rstest]
257 #[case::null(ArrayCommand::Null, "null")]
258 #[case::bool_true(ArrayCommand::Bool(true), "true")]
259 #[case::bool_false(ArrayCommand::Bool(false), "false")]
260 #[case::raw(ArrayCommand::Raw("x y z"), "x y z")]
261 #[case::string(ArrayCommand::String("asdf"), r#""asdf""#)]
262 #[case::string_escaped(ArrayCommand::String("\r\n"), r#""\r\n""#)]
263 #[case::u8(ArrayCommand::U8(2), "2")]
264 #[case::i8(ArrayCommand::I8(-3), "-3")]
265 #[case::u16(ArrayCommand::U16(4), "4")]
266 #[case::i16(ArrayCommand::I16(-5), "-5")]
267 #[case::u32(ArrayCommand::U32(6), "6")]
268 #[case::i32(ArrayCommand::I32(-7), "-7")]
269 #[case::u64(ArrayCommand::U64(8), "8")]
270 #[case::i64(ArrayCommand::I64(-9), "-9")]
271 #[case::u128(ArrayCommand::U128(10), "10")]
272 #[case::i128(ArrayCommand::I128(-11), "-11")]
273 #[case::u128(ArrayCommand::Usize(12), "12")]
274 #[case::i128(ArrayCommand::Isize(-13), "-13")]
275 #[case::f64(ArrayCommand::F64(2.0), "2")]
276 #[case::f64_exp_5(ArrayCommand::F64(1.234e5), "123400")]
277 #[case::f64_exp_10(ArrayCommand::F64(1.234e10), "1.234e10")]
278 #[case::f64_exp_20(ArrayCommand::F64(1.234e20), "1.234e20")]
279 #[case::f64_exp_neg_3(ArrayCommand::F64(1.234e-3), "0.001234")]
280 #[case::f64_exp_neg_10(ArrayCommand::F64(1.234e-10), "1.234e-10")]
281 #[case::f64_neg(ArrayCommand::F64(-2.0), "-2")]
282 #[case::f64_neg_exp_5(ArrayCommand::F64(-1.234e5), "-123400")]
283 #[case::f64_neg_exp_10(ArrayCommand::F64(-1.234e10), "-1.234e10")]
284 #[case::f64_neg_exp_20(ArrayCommand::F64(-1.234e20), "-1.234e20")]
285 #[case::f64_neg_exp_neg_3(ArrayCommand::F64(-1.234e-3), "-0.001234")]
286 #[case::f64_neg_exp_neg_10(ArrayCommand::F64(-1.234e-10), "-1.234e-10")]
287 #[case::f64_inf(ArrayCommand::F64(f64::INFINITY), "null")]
288 #[case::f64_neg_inf(ArrayCommand::F64(f64::NEG_INFINITY), "null")]
289 #[case::f64_nan(ArrayCommand::F64(f64::NAN), "null")]
290 #[case::f32(ArrayCommand::F32(2.0), "2")]
291 #[case::f32_exp_5(ArrayCommand::F32(1.234e5), "123400")]
292 #[case::f32_exp_10(ArrayCommand::F32(1.234e10), "1.234e10")]
293 #[case::f32_exp_20(ArrayCommand::F32(1.234e20), "1.234e20")]
294 #[case::f32_exp_neg_3(ArrayCommand::F32(1.234e-3), "0.001234")]
295 #[case::f32_exp_neg_10(ArrayCommand::F32(1.234e-10), "1.234e-10")]
296 #[case::f32_neg(ArrayCommand::F32(-2.0), "-2")]
297 #[case::f32_neg_exp_5(ArrayCommand::F32(-1.234e5), "-123400")]
298 #[case::f32_neg_exp_10(ArrayCommand::F32(-1.234e10), "-1.234e10")]
299 #[case::f32_neg_exp_20(ArrayCommand::F32(-1.234e20), "-1.234e20")]
300 #[case::f32_neg_exp_neg_3(ArrayCommand::F32(-1.234e-3), "-0.001234")]
301 #[case::f32_neg_exp_neg_10(ArrayCommand::F32(-1.234e-10), "-1.234e-10")]
302 #[case::f32_inf(ArrayCommand::F32(f32::INFINITY), "null")]
303 #[case::f32_neg_inf(ArrayCommand::F32(f32::NEG_INFINITY), "null")]
304 #[case::f32_nan(ArrayCommand::F32(f32::NAN), "null")]
305 #[tokio::test]
306 async fn test_write_value(#[case] cmd: ArrayCommand, #[case] expected: &str) -> io::Result<()> {
307 {
308 let mut buf = Vec::new();
309 let mut writer = JsonWriter::new_compact(&mut buf);
310 {
311 let mut array_ser = JsonArray::new(&mut writer).await?;
312 cmd.apply(&mut array_ser).await;
313 array_ser.end().await?;
314 }
315
316 let actual = String::from_utf8(buf).unwrap();
317 let expected = format!("[{}]", expected);
318 assert_eq!(actual, expected);
319 }
320
321 {
323 let mut buf = Vec::new();
324 let mut writer = JsonWriter::new_compact(&mut buf);
325 {
326 let mut array_ser = JsonArray::new(&mut writer).await?;
327 array_ser.write_null_value().await?;
328 cmd.apply(&mut array_ser).await;
329 array_ser.end().await?;
330 }
331
332 let actual = String::from_utf8(buf).unwrap();
333 let expected = format!("[null,{}]", expected);
334 assert_eq!(actual, expected);
335 }
336
337 Ok(())
338 }
339}