sonic_rs/lazyvalue/
iterator.rs

1use std::borrow::Cow;
2
3use crate::{
4    error::Result,
5    input::{JsonInput, JsonSlice},
6    lazyvalue::LazyValue,
7    parser::{Pair, Parser, DEFAULT_KEY_BUF_CAPACITY},
8    reader::{Read, Reader},
9};
10/// A lazied iterator for JSON object text. It will parse the JSON when iterating.
11///
12/// The item of the iterator is [`Result<LazyValue>`][`crate::LazyValue`].
13///
14/// # Examples
15///```
16/// use faststr::FastStr;
17/// use sonic_rs::{to_object_iter, JsonValueTrait};
18///
19/// let json = FastStr::from(r#"{"a": null, "b":[1, 2, 3]}"#);
20/// let iter = to_object_iter(&json);
21///
22/// for ret in iter {
23///     // deal with errors
24///     if ret.is_err() {
25///         println!("{}", ret.unwrap_err());
26///         return;
27///     }
28///     let (k, v) = ret.unwrap();
29///     if k == "a" {
30///         assert!(v.is_null());
31///     } else if k == "b" {
32///         assert_eq!(v.as_raw_str(), "[1, 2, 3]");
33///     }
34/// }
35/// ```
36pub struct ObjectJsonIter<'de> {
37    parser: Parser<Read<'de>>,
38    strbuf: Vec<u8>,
39    first: bool,
40    ending: bool,
41    skip_strict: bool,
42}
43
44/// A lazied iterator for JSON array text. It will parse the JSON when iterating.
45///
46/// The item of the iterator is [`Result<LazyValue>`][`crate::LazyValue`].
47///
48/// # Examples
49/// ```
50/// use sonic_rs::{to_array_iter, JsonValueTrait};
51///
52/// let iter = to_array_iter(r#"[0, 1, 2, 3, 4, 5, 6]"#);
53/// for (i, ret) in iter.enumerate() {
54///     let lv = ret.unwrap(); // get lazyvalue
55///     assert_eq!(i.to_string(), lv.as_raw_str()); // lv is not parsed
56///     assert_eq!(i, lv.as_u64().unwrap() as usize);
57/// }
58///
59/// let iter = to_array_iter(r#"[1, 2, 3, 4, 5, 6"#);
60/// for elem in iter {
61///     // do something for each elem
62///     // deal with errors when invalid json
63///     if elem.is_err() {
64///         assert!(elem
65///             .unwrap_err()
66///             .to_string()
67///             .contains("Expected this character to be either a ',' or a ']'"));
68///     }
69/// }
70/// ```
71pub struct ArrayJsonIter<'de> {
72    parser: Parser<Read<'de>>,
73    first: bool,
74    ending: bool,
75    skip_strict: bool,
76}
77
78impl<'de> ObjectJsonIter<'de> {
79    // input is inner json, expected always be validated and well-formed
80    pub(crate) fn new_inner(input: JsonSlice<'de>) -> Self {
81        Self {
82            parser: Parser::new(Read::new_in(input, false)),
83            strbuf: Vec::with_capacity(DEFAULT_KEY_BUF_CAPACITY),
84            first: true,
85            ending: false,
86            skip_strict: false,
87        }
88    }
89
90    pub(crate) fn new<I: JsonInput<'de>>(input: I, skip_strict: bool) -> Self {
91        let validate_utf8 = skip_strict
92            .then_some(input.need_utf8_valid())
93            .unwrap_or_default();
94
95        Self {
96            parser: Parser::new(Read::new_in(input.to_json_slice(), validate_utf8)),
97            strbuf: Vec::with_capacity(DEFAULT_KEY_BUF_CAPACITY),
98            first: true,
99            ending: false,
100            skip_strict,
101        }
102    }
103
104    fn next_entry_impl(&mut self) -> Option<Result<(Cow<'de, str>, LazyValue<'de>)>> {
105        if self.ending {
106            return None;
107        }
108
109        if self.first {
110            // check invalid utf8
111            if let Err(err) = self.parser.read.check_utf8_final() {
112                self.ending = true;
113                return Some(Err(err));
114            }
115        }
116
117        match self
118            .parser
119            .parse_entry_lazy(&mut self.strbuf, &mut self.first, self.skip_strict)
120        {
121            Ok(ret) => {
122                if let Some(Pair { key, val, status }) = ret {
123                    let val = self.parser.read.slice_ref(val);
124                    Some(Ok(LazyValue::new(val, status.into())).map(|v| (key, v)))
125                } else {
126                    self.ending = true;
127                    None
128                }
129            }
130            Err(err) => {
131                self.ending = true;
132                Some(Err(err))
133            }
134        }
135    }
136}
137
138impl<'de> ArrayJsonIter<'de> {
139    // input is inner json, expected always be validated and well-formed
140    pub(crate) fn new_inner(input: JsonSlice<'de>) -> Self {
141        Self {
142            parser: Parser::new(Read::new_in(input, false)),
143            first: true,
144            ending: false,
145            skip_strict: false,
146        }
147    }
148
149    pub(crate) fn new<I: JsonInput<'de>>(input: I, skip_strict: bool) -> Self {
150        let validate_utf8 = skip_strict
151            .then_some(input.need_utf8_valid())
152            .unwrap_or_default();
153
154        Self {
155            parser: Parser::new(Read::new_in(input.to_json_slice(), validate_utf8)),
156            first: true,
157            ending: false,
158            skip_strict,
159        }
160    }
161
162    fn next_elem_impl(&mut self) -> Option<Result<LazyValue<'de>>> {
163        if self.ending {
164            return None;
165        }
166
167        if self.first {
168            // check invalid utf8
169            if let Err(err) = self.parser.read.check_utf8_final() {
170                self.ending = true;
171                return Some(Err(err));
172            }
173        }
174
175        match self
176            .parser
177            .parse_array_elem_lazy(&mut self.first, self.skip_strict)
178        {
179            Ok(ret) => {
180                if let Some((val, status)) = ret {
181                    let val = self.parser.read.slice_ref(val);
182                    Some(Ok(LazyValue::new(val, status.into())))
183                } else {
184                    self.ending = true;
185                    None
186                }
187            }
188            Err(err) => {
189                self.ending = true;
190                Some(Err(err))
191            }
192        }
193    }
194}
195
196/// Traverse the JSON object text through a lazy iterator. The JSON parsing will doing when
197/// iterating.
198///
199/// The item of the iterator is a key-value pair: ([FastStr][`faststr::FastStr`],
200/// [`Result<LazyValue>`][`crate::LazyValue`]).
201///
202/// # Errors
203///
204/// If the JSON is empty, not a object or parse error, the result will be Err and the `next()` will
205/// return `None`.
206///
207/// # Examples
208///
209/// ```
210/// # use sonic_rs::to_object_iter;
211/// use faststr::FastStr;
212/// use sonic_rs::JsonValueTrait;
213///
214/// let json = FastStr::from(r#"{"a": null, "b":[1, 2, 3]}"#);
215/// for ret in to_object_iter(&json) {
216///     assert!(ret.is_ok());
217///     let (k, v) = ret.unwrap();
218///     if k == "a" {
219///         assert!(v.is_null());
220///     } else if k == "b" {
221///         assert_eq!(v.as_raw_str(), "[1, 2, 3]");
222///     }
223/// }
224///
225/// // the JSON is invalid, will report error when encountering the error
226/// for (i, ret) in to_object_iter(r#"{"a": null, "b":[1, 2, 3"#).enumerate() {
227///     if i == 0 {
228///         assert!(ret.is_ok());
229///     }
230///     if i == 1 {
231///         assert!(ret.is_err());
232///     }
233/// }
234/// ```
235pub fn to_object_iter<'de, I: JsonInput<'de>>(json: I) -> ObjectJsonIter<'de> {
236    ObjectJsonIter::new(json, true)
237}
238
239/// Traverse the JSON array text through a lazy iterator. The JSON parsing will doing when
240/// iterating.
241///
242/// The item of the iterator is [`Result<LazyValue>`][`crate::LazyValue`].
243///
244/// # Errors
245///
246/// If the JSON is empty, not array or parse error, it will return Err and `next()` will return
247/// `None`.
248///
249/// # Examples
250///
251/// ```
252/// # use sonic_rs::to_array_iter;
253/// use sonic_rs::JsonValueTrait;
254///
255/// for (i, ret) in to_array_iter(r#"[0, 1, 2, 3, 4, 5, 6]"#).enumerate() {
256///     let lv = ret.unwrap(); // get lazyvalue
257///     assert_eq!(i.to_string(), lv.as_raw_str()); // lv is not parsed
258///     assert_eq!(i, lv.as_u64().unwrap() as usize);
259/// }
260///
261/// for elem in to_array_iter(r#"[1, 2, 3, 4, 5, 6"#) {
262///     // do something for each elem
263///     // deal with errors when invalid json
264///     if elem.is_err() {
265///         assert!(elem
266///             .unwrap_err()
267///             .to_string()
268///             .contains("Expected this character to be either a ',' or a ']'"));
269///     }
270/// }
271/// ```
272pub fn to_array_iter<'de, I: JsonInput<'de>>(json: I) -> ArrayJsonIter<'de> {
273    ArrayJsonIter::new(json, true)
274}
275
276/// Traverse the JSON text through a lazy object iterator. The JSON parsing will doing when
277/// iterating.
278///
279/// The item of the iterator is a key-value pair: ([FastStr][`faststr::FastStr`],
280/// [`Result<LazyValue>`][`crate::LazyValue`]).
281///
282/// # Errors
283///
284/// If the JSON is empty, or not a object, the result will be Err and the `next()` will return
285/// `None`.
286///
287/// # Safety
288///
289/// If the json is invalid, the result is undefined.
290///
291/// # Examples
292///
293/// ```
294/// # use sonic_rs::to_object_iter_unchecked;
295/// use faststr::FastStr;
296/// use sonic_rs::JsonValueTrait;
297///
298/// let json = FastStr::from(r#"{"a": null, "b":[1, 2, 3]}"#);
299/// for ret in unsafe { to_object_iter_unchecked(&json) } {
300///     assert!(ret.is_ok());
301///     let (k, v) = ret.unwrap();
302///     if k == "a" {
303///         assert!(v.is_null());
304///     } else if k == "b" {
305///         assert_eq!(v.as_raw_str(), "[1, 2, 3]");
306///     }
307/// }
308/// ```
309pub unsafe fn to_object_iter_unchecked<'de, I: JsonInput<'de>>(json: I) -> ObjectJsonIter<'de> {
310    ObjectJsonIter::new(json, false)
311}
312
313/// Traverse the JSON text through a lazy object iterator. The JSON parsing will doing when
314/// iterating.
315///
316/// The item of the iterator is [`Result<LazyValue>`][`crate::LazyValue`].
317///
318/// # Errors
319///
320/// If the JSON is empty, or not a array, the result will be Err and the `next()` will return
321/// `None`.
322///
323/// # Safety
324///
325/// If the json is invalid, the result is undefined.
326///
327/// # Examples
328/// ```
329/// # use sonic_rs::to_array_iter_unchecked;
330/// use sonic_rs::JsonValueTrait;
331///
332/// for (i, ret) in unsafe { to_array_iter_unchecked(r#"[0, 1, 2, 3, 4, 5, 6]"#) }.enumerate() {
333///     let lv = ret.unwrap(); // get lazyvalue
334///     assert_eq!(i.to_string(), lv.as_raw_str()); // lv is not parsed
335///     assert_eq!(i, lv.as_u64().unwrap() as usize);
336/// }
337///
338/// // the JSON is empty
339/// for elem in unsafe { to_array_iter_unchecked("") } {
340///     assert!(elem.is_err());
341/// }
342/// ```
343pub unsafe fn to_array_iter_unchecked<'de, I: JsonInput<'de>>(json: I) -> ArrayJsonIter<'de> {
344    ArrayJsonIter::new(json, false)
345}
346
347impl<'de> Iterator for ObjectJsonIter<'de> {
348    type Item = Result<(Cow<'de, str>, LazyValue<'de>)>;
349
350    fn next(&mut self) -> Option<Self::Item> {
351        self.next_entry_impl()
352    }
353}
354
355impl<'de> Iterator for ArrayJsonIter<'de> {
356    type Item = Result<LazyValue<'de>>;
357
358    fn next(&mut self) -> Option<Self::Item> {
359        self.next_elem_impl()
360    }
361}
362
363#[cfg(test)]
364mod test {
365    use bytes::Bytes;
366
367    use super::*;
368    use crate::{value::JsonValueTrait, JsonType};
369
370    #[test]
371    fn test_object_iter() {
372        let json = Bytes::from(
373            r#"{
374            "string": "Hello, world!",
375            "number": 42,
376            "boolean": true,
377            "null": null,
378            "array": ["foo","bar","baz"],
379            "object": {"name": "Alice"},
380            "empty": {},
381            "": [],
382            "escaped\"": "\"\"",
383            "\t": "\n",
384            "\u0000": "\u0001"
385        }"#,
386        );
387        let _v: serde_json::Value = serde_json::from_slice(json.as_ref()).unwrap();
388        let mut iter = to_object_iter(&json);
389        let mut iter_unchecked = unsafe { to_object_iter_unchecked(&json) };
390
391        let mut test_ok = |key: &str, val: &str, typ: JsonType| {
392            let ret = iter.next().unwrap().unwrap();
393            assert_eq!(ret.0.as_ref(), key);
394            assert_eq!(
395                ret.1.as_raw_str().as_bytes(),
396                val.as_bytes(),
397                "key is {} ",
398                key
399            );
400            assert_eq!(ret.1.get_type(), typ);
401
402            let ret = iter_unchecked.next().unwrap().unwrap();
403            assert_eq!(ret.0.as_ref(), key);
404            assert_eq!(
405                ret.1.as_raw_str().as_bytes(),
406                val.as_bytes(),
407                "key is {} ",
408                key
409            );
410            assert_eq!(ret.1.get_type(), typ);
411        };
412        test_ok("string", r#""Hello, world!""#, JsonType::String);
413        test_ok("number", "42", JsonType::Number);
414        test_ok("boolean", "true", JsonType::Boolean);
415        test_ok("null", "null", JsonType::Null);
416        test_ok("array", r#"["foo","bar","baz"]"#, JsonType::Array);
417        test_ok("object", r#"{"name": "Alice"}"#, JsonType::Object);
418        test_ok("empty", r#"{}"#, JsonType::Object);
419        test_ok("", r#"[]"#, JsonType::Array);
420        test_ok("escaped\"", r#""\"\"""#, JsonType::String);
421        test_ok("\t", r#""\n""#, JsonType::String);
422        test_ok("\x00", r#""\u0001""#, JsonType::String);
423        assert!(iter.next().is_none());
424        assert!(iter.next().is_none());
425
426        let json = Bytes::from("{}");
427        let mut iter = to_object_iter(&json);
428        assert!(iter.next().is_none());
429        assert!(iter.next().is_none());
430        assert!(iter.next().is_none());
431
432        let json = Bytes::from("{xxxxxx");
433        let mut iter = to_object_iter(&json);
434        assert!(iter.next().unwrap().is_err());
435        assert!(iter.next().is_none());
436    }
437
438    #[test]
439    fn test_array_iter() {
440        let json = Bytes::from(
441            r#"[
442            "",
443            "\\\"\"",
444            "{\"a\":null}",
445            "Hello, world!",
446            0,
447            1,
448            11,
449            1000,
450            42,
451            42.0,
452            42e-1,
453            4.2e+1,
454            2333.2e+1,
455            0.0000000999e8,
456            true,
457            null,
458            ["foo","bar","baz"],
459            {"name": "Alice"},
460            [],
461            {}
462        ]"#,
463        );
464        let mut iter = to_array_iter(&json);
465        let mut iter_unchecked = unsafe { to_array_iter_unchecked(&json) };
466        let mut test_ok = |val: &str, typ: JsonType| {
467            let ret: LazyValue<'_> = iter.next().unwrap().unwrap();
468            assert_eq!(ret.as_raw_str(), val);
469            assert_eq!(ret.get_type(), typ);
470
471            let ret = iter_unchecked.next().unwrap().unwrap();
472            assert_eq!(ret.as_raw_str().as_bytes(), val.as_bytes());
473            assert_eq!(ret.get_type(), typ);
474        };
475
476        test_ok(r#""""#, JsonType::String);
477        test_ok(r#""\\\"\"""#, JsonType::String);
478        test_ok(r#""{\"a\":null}""#, JsonType::String);
479        test_ok(r#""Hello, world!""#, JsonType::String);
480        test_ok("0", JsonType::Number);
481        test_ok("1", JsonType::Number);
482        test_ok("11", JsonType::Number);
483        test_ok("1000", JsonType::Number);
484        test_ok("42", JsonType::Number);
485        test_ok("42.0", JsonType::Number);
486        test_ok("42e-1", JsonType::Number);
487        test_ok("4.2e+1", JsonType::Number);
488        test_ok("2333.2e+1", JsonType::Number);
489        test_ok("0.0000000999e8", JsonType::Number);
490        test_ok("true", JsonType::Boolean);
491        test_ok("null", JsonType::Null);
492        test_ok(r#"["foo","bar","baz"]"#, JsonType::Array);
493        test_ok(r#"{"name": "Alice"}"#, JsonType::Object);
494        test_ok(r#"[]"#, JsonType::Array);
495        test_ok(r#"{}"#, JsonType::Object);
496        assert!(iter.next().is_none());
497        assert!(iter.next().is_none());
498
499        let json = Bytes::from("[]");
500        let mut iter = to_array_iter(&json);
501        assert!(iter.next().is_none());
502        assert!(iter.next().is_none());
503        assert!(iter.next().is_none());
504
505        let json = Bytes::from("[xxxxxx");
506        let mut iter = to_array_iter(&json);
507        assert!(iter.next().unwrap().is_err());
508        assert!(iter.next().is_none());
509    }
510
511    #[test]
512    fn test_iter_deserialize() {
513        let json = Bytes::from(r#"[1, 2, 3, 4, 5, 6]"#);
514        let iter = to_array_iter(&json);
515        let out: Vec<u8> = iter
516            .flatten()
517            .map(|e| crate::from_str::<u8>(e.as_raw_str()).unwrap_or_default())
518            .collect();
519        assert_eq!(out.as_slice(), &[1, 2, 3, 4, 5, 6]);
520
521        let json = Bytes::from(r#"[1, true, "hello", null, 5, 6]"#);
522        let iter = to_array_iter(&json);
523        let out: Vec<JsonType> = iter.map(|e| e.get_type()).collect();
524        println!("array elem type is {:?}", out);
525    }
526
527    #[test]
528    fn test_num_iter() {
529        for i in to_array_iter("[6,-9E6]") {
530            println!("{:?}", i.unwrap().as_raw_str());
531        }
532    }
533
534    #[test]
535    fn test_json_iter_for_utf8() {
536        let data = [b'[', b'"', 0, 0, 0, 0x80, 0x90, b'"', b']'];
537        let iter = to_array_iter(&data[..]);
538        for item in iter {
539            assert_eq!(
540                item.err().unwrap().to_string(),
541                "Invalid UTF-8 characters in json at line 1 column \
542                 5\n\n\t[\"\0\0\0��\"]\n\t.....^...\n"
543            );
544        }
545
546        let data = [
547            b'{', b'"', 0, 0, 0, 0x80, 0x90, b'"', b':', b'"', b'"', b'}',
548        ];
549        let iter = to_object_iter(&data[..]);
550        for item in iter {
551            assert_eq!(
552                item.err().unwrap().to_string(),
553                "Invalid UTF-8 characters in json at line 1 column \
554                 5\n\n\t{\"\0\0\0��\":\"\"}\n\t.....^......\n"
555            );
556        }
557    }
558}