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