sonic_rs/lazyvalue/
get.rs

1use bytes::Bytes;
2use faststr::FastStr;
3
4use super::LazyValue;
5use crate::{
6    error::Result,
7    index::Index,
8    input::JsonInput,
9    parser::Parser,
10    pointer::PointerTree,
11    reader::{Read, Reader},
12    util::utf8::from_utf8,
13};
14
15/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
16///
17/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
18///
19/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
20///
21/// # Safety
22///
23/// The JSON must be valid and well-formed, otherwise it may return unexpected result.
24///
25/// # Examples
26/// ```
27/// # use sonic_rs::get_from_str_unchecked;
28///
29/// // get from the &[&str]
30/// let lv = unsafe { get_from_str_unchecked(r#"{"a": 1}"#, &["a"]).unwrap() };
31/// assert_eq!(lv.as_raw_str(), "1");
32///
33/// // get from the &[usize]
34/// let lv = unsafe { get_from_str_unchecked(r#"[0, 1, "two"]"#, &[2]).unwrap() };
35/// assert_eq!(lv.as_raw_str(), "\"two\"");
36///
37/// // get from pointer!
38/// use sonic_rs::pointer;
39/// let lv =
40///     unsafe { get_from_str_unchecked(r#"{"a": [0, 1, "two"]}"#, &pointer!["a", 2]).unwrap() };
41/// assert_eq!(lv.as_raw_str(), "\"two\"");
42///
43/// // not found the field "a"
44/// let lv = unsafe { get_from_str_unchecked(r#"{"a": 1}"#, &["b"]) };
45/// assert!(lv.unwrap_err().is_not_found());
46///
47/// // the type of JSON is unmatched, expect it is a object
48/// let lv = unsafe { get_from_str_unchecked(r#"[1, 2, 3]"#, &["b"]) };
49/// assert!(lv.unwrap_err().is_unmatched_type());
50/// ```
51pub unsafe fn get_from_str_unchecked<Path: IntoIterator>(
52    json: &str,
53    path: Path,
54) -> Result<LazyValue<'_>>
55where
56    Path::Item: Index,
57{
58    get_unchecked(json, path)
59}
60
61/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
62///
63/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
64///
65/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
66///
67/// # Safety
68///
69/// The JSON must be valid and well-formed, otherwise it may return unexpected result.
70pub unsafe fn get_from_bytes_unchecked<Path: IntoIterator>(
71    json: &Bytes,
72    path: Path,
73) -> Result<LazyValue<'_>>
74where
75    Path::Item: Index,
76{
77    get_unchecked(json, path)
78}
79
80/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
81///
82/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
83///
84/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
85///
86/// # Safety
87///
88/// The JSON must be valid and well-formed, otherwise it may return unexpected result.
89///
90/// # Examples
91///
92/// ```
93/// # use sonic_rs::get_from_faststr_unchecked;
94///
95/// // get from the &[&str]
96/// let fs = faststr::FastStr::new(r#"{"a": 1}"#);
97/// let lv = unsafe { get_from_faststr_unchecked(&fs, &["a"]).unwrap() };
98/// assert_eq!(lv.as_raw_str(), "1");
99///
100/// // not found the field "a"
101/// let lv = unsafe { get_from_faststr_unchecked(&fs, &["b"]) };
102/// assert!(lv.unwrap_err().is_not_found());
103///
104/// // get from the &[usize]
105/// let fs = faststr::FastStr::new(r#"[0, 1, "two"]"#);
106/// let lv = unsafe { get_from_faststr_unchecked(&fs, &[2]).unwrap() };
107/// assert_eq!(lv.as_raw_str(), "\"two\"");
108///
109/// // get from pointer!
110/// use sonic_rs::pointer;
111/// let fs = faststr::FastStr::new(r#"{"a": [0, 1, "two"]}"#);
112/// let lv = unsafe { get_from_faststr_unchecked(&fs, &pointer!["a", 2]).unwrap() };
113/// assert_eq!(lv.as_raw_str(), "\"two\"");
114///
115/// /// the type of JSON is unmatched, expect it is a object
116/// let lv = unsafe { get_from_faststr_unchecked(&fs, &pointer!["a", "get key from array"]) };
117/// assert!(lv.unwrap_err().is_unmatched_type());
118/// ```
119pub unsafe fn get_from_faststr_unchecked<Path: IntoIterator>(
120    json: &FastStr,
121    path: Path,
122) -> Result<LazyValue<'_>>
123where
124    Path::Item: Index,
125{
126    get_unchecked(json, path)
127}
128
129/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
130///
131/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
132///
133/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
134///
135/// # Safety
136/// The JSON must be valid and well-formed, otherwise it may return unexpected result.
137pub unsafe fn get_from_slice_unchecked<Path: IntoIterator>(
138    json: &[u8],
139    path: Path,
140) -> Result<LazyValue<'_>>
141where
142    Path::Item: Index,
143{
144    get_unchecked(json, path)
145}
146
147/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
148///
149/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
150///
151/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
152///
153/// The input `json` is allowed to be `&FastStr`, `&[u8]`, `&str`, `&String` or `&bytes::Bytes`.
154///
155/// # Safety
156/// The JSON must be valid and well-formed, otherwise it may return unexpected result.
157///
158/// # Examples
159/// ```
160/// use faststr::FastStr;
161/// use sonic_rs::get_unchecked;
162///
163/// let lv = unsafe { get_unchecked(r#"{"a": 1}"#, &["a"]).unwrap() };
164/// assert_eq!(lv.as_raw_str(), "1");
165///
166/// /// not found the field "a"
167/// let fs = FastStr::new(r#"{"a": 1}"#);
168/// let lv = unsafe { get_unchecked(&fs, &["b"]) };
169/// assert!(lv.unwrap_err().is_not_found());
170/// ```
171pub unsafe fn get_unchecked<'de, Input, Path: IntoIterator>(
172    json: Input,
173    path: Path,
174) -> Result<LazyValue<'de>>
175where
176    Input: JsonInput<'de>,
177    Path::Item: Index,
178{
179    let slice = json.to_u8_slice();
180    let reader = Read::new(slice, false);
181    let mut parser = Parser::new(reader);
182    let (sub, status) = parser.get_from_with_iter_unchecked(path)?;
183    Ok(LazyValue::new(json.from_subset(sub), status.into()))
184}
185
186/// get_many returns multiple fields from the `PointerTree`.
187///
188/// The result is a `Result<Vec<Option<LazyValue>>>`. The order of the `Vec` is same as the order of
189/// the tree.
190///
191/// If a key is unknown, the value at the corresponding position in `Vec` will be None.
192/// If json is invalid, or the field not be found, it will return a err.
193///
194/// # Safety
195/// The JSON must be valid and well-formed, otherwise it may return unexpected result.
196///
197/// # Examples
198/// ```
199/// # use sonic_rs::pointer;
200/// # use sonic_rs::PointerTree;
201///
202/// let json = r#"
203/// {"u": 123, "a": {"b" : {"c": [null, "found"]}}}"#;
204///
205/// // build a pointer tree, representing multiple json path
206/// let mut tree = PointerTree::new();
207///
208/// tree.add_path(&["u"]);
209/// tree.add_path(&["unknown_key"]);
210/// tree.add_path(&pointer!["a", "b", "c", 1]);
211///
212/// let nodes = unsafe { sonic_rs::get_many_unchecked(json, &tree) };
213///
214/// match nodes {
215///     Ok(vals) => {
216///         assert_eq!(vals[0].as_ref().unwrap().as_raw_str(), "123");
217///         assert!(vals[1].is_none());
218///         assert_eq!(vals[2].as_ref().unwrap().as_raw_str(), "\"found\"");
219///     }
220///     Err(e) => {
221///         panic!("err: {:?}", e)
222///     }
223/// }
224/// ```
225pub unsafe fn get_many_unchecked<'de, Input>(
226    json: Input,
227    tree: &PointerTree,
228) -> Result<Vec<Option<LazyValue<'de>>>>
229where
230    Input: JsonInput<'de>,
231{
232    let slice = json.to_u8_slice();
233    let reader = Read::new(slice, false);
234    let mut parser = Parser::new(reader);
235    parser.get_many(tree, false)
236}
237
238/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
239///
240/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
241///
242/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
243///
244/// # Examples
245/// ```
246/// # use sonic_rs::get_from_str;
247///
248/// // get from the &[&str]
249/// let lv = get_from_str(r#"{"a": 1}"#, &["a"]).unwrap();
250/// assert_eq!(lv.as_raw_str(), "1");
251///
252/// // get from the &[usize]
253/// let lv = get_from_str(r#"[0, 1, "two"]"#, &[2]).unwrap();
254/// assert_eq!(lv.as_raw_str(), "\"two\"");
255///
256/// // get from pointer!
257/// use sonic_rs::pointer;
258/// let lv = get_from_str(r#"{"a": [0, 1, "two"]}"#, &pointer!["a", 2]).unwrap();
259/// assert_eq!(lv.as_raw_str(), "\"two\"");
260///
261/// // not found the field "a"
262/// let lv = get_from_str(r#"{"a": 1}"#, &["b"]);
263/// assert!(lv.unwrap_err().is_not_found());
264///
265/// // the type of JSON is unmatched, expect it is a object
266/// let lv = get_from_str(r#"[1, 2, 3]"#, &["b"]);
267/// assert!(lv.unwrap_err().is_unmatched_type());
268/// ```
269pub fn get_from_str<Path: IntoIterator>(json: &str, path: Path) -> Result<LazyValue<'_>>
270where
271    Path::Item: Index,
272{
273    get(json, path)
274}
275
276/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
277///
278/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
279///
280/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
281///
282/// # Examples
283/// ```
284/// use sonic_rs::get_from_slice;
285/// let lv = get_from_slice(br#"{"a": 1}"#, &["a"]).unwrap();
286/// assert_eq!(lv.as_raw_str(), "1");
287///
288/// /// not found the field "a"
289/// let lv = get_from_slice(br#"{"a": 1}"#, &["b"]);
290/// assert!(lv.is_err());
291/// ```
292pub fn get_from_slice<Path: IntoIterator>(json: &[u8], path: Path) -> Result<LazyValue<'_>>
293where
294    Path::Item: Index,
295{
296    get(json, path)
297}
298
299/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
300///
301/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
302///
303/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
304///
305/// # Examples
306/// ```
307/// # use sonic_rs::get_from_bytes;
308/// use bytes::Bytes;
309///
310/// let bs = Bytes::from(r#"{"a": 1}"#);
311/// let lv = get_from_bytes(&bs, &["a"]).unwrap();
312///
313/// assert_eq!(lv.as_raw_str(), "1");
314///
315/// /// not found the field "a"
316/// let lv = get_from_bytes(&bs, &["b"]);
317/// assert!(lv.is_err());
318/// ```
319pub fn get_from_bytes<Path: IntoIterator>(json: &Bytes, path: Path) -> Result<LazyValue<'_>>
320where
321    Path::Item: Index,
322{
323    get(json, path)
324}
325
326/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
327///
328/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
329///
330/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
331///
332/// # Examples
333///
334/// ```
335/// # use sonic_rs::get_from_faststr;
336///
337/// // get from the &[&str]
338/// let fs = faststr::FastStr::new(r#"{"a": 1}"#);
339/// let lv = get_from_faststr(&fs, &["a"]).unwrap();
340/// assert_eq!(lv.as_raw_str(), "1");
341///
342/// // not found the field "a"
343/// let lv = get_from_faststr(&fs, &["b"]);
344/// assert!(lv.unwrap_err().is_not_found());
345///
346/// // get from the &[usize]
347/// let fs = faststr::FastStr::new(r#"[0, 1, "two"]"#);
348/// let lv = get_from_faststr(&fs, &[2]).unwrap();
349/// assert_eq!(lv.as_raw_str(), "\"two\"");
350///
351/// // get from pointer!
352/// use sonic_rs::pointer;
353/// let fs = faststr::FastStr::new(r#"{"a": [0, 1, "two"]}"#);
354/// let lv = get_from_faststr(&fs, &pointer!["a", 2]).unwrap();
355/// assert_eq!(lv.as_raw_str(), "\"two\"");
356///
357/// /// the type of JSON is unmatched, expect it is a object
358/// let lv = get_from_faststr(&fs, &pointer!["a", "get key from array"]);
359/// assert!(lv.unwrap_err().is_unmatched_type());
360/// ```
361pub fn get_from_faststr<Path: IntoIterator>(json: &FastStr, path: Path) -> Result<LazyValue<'_>>
362where
363    Path::Item: Index,
364{
365    get(json, path)
366}
367
368/// Gets a field from a `path`. And return it as a [`Result<LazyValue>`][crate::LazyValue].
369///
370/// If not found, return an error. If the `path` is empty, return the whole JSON as a `LazyValue`.
371///
372/// The `Item` of the `path` should implement the [`Index`][crate::index::Index] trait.
373///
374/// The input `json` is allowed to be `&FastStr`, `&[u8]`, `&str`, `&String` or `&bytes::Bytes`.
375///
376/// # Safety
377/// The JSON must be valid and well-formed, otherwise it may return unexpected result.
378///
379/// # Examples
380/// ```
381/// use bytes::Bytes;
382/// use faststr::FastStr;
383/// use sonic_rs::get;
384///
385/// let lv = get(r#"{"a": 1}"#, &["a"]).unwrap();
386/// assert_eq!(lv.as_raw_str(), "1");
387///
388/// /// not found the field "a"
389/// let fs = FastStr::new(r#"{"a": 1}"#);
390/// let lv = get(&fs, &["b"]);
391/// assert!(lv.is_err());
392///
393/// /// the JSON is invalid
394/// let b = Bytes::from(r#"{"a": tru }"#);
395/// let lv = get(&b, &["a"]);
396/// assert!(lv.is_err());
397/// ```
398pub fn get<'de, Input, Path: IntoIterator>(json: Input, path: Path) -> Result<LazyValue<'de>>
399where
400    Input: JsonInput<'de>,
401    Path::Item: Index,
402{
403    let slice = json.to_u8_slice();
404    let reader = Read::new(slice, false);
405    let mut parser = Parser::new(reader);
406    let (sub, status) = parser.get_from_with_iter(path)?;
407    let lv = LazyValue::new(json.from_subset(sub), status.into());
408
409    // validate the utf-8 if slice
410    let index = parser.read.index();
411    if json.need_utf8_valid() {
412        from_utf8(&slice[..index])?;
413    }
414    Ok(lv)
415}
416
417/// get_many returns multiple fields from the [`PointerTree`].
418///
419/// The result is a `Result<Vec<Option<LazyValue>>>`. The order of the `Vec` is same as the order of
420/// the tree.
421///
422/// If a key is unknown, the value at the corresponding position in `Vec` will be None.  
423/// If json is invalid, or the field not be found, it will return a err.
424///
425/// # Examples
426/// ```
427/// # use sonic_rs::pointer;
428/// # use sonic_rs::PointerTree;
429///
430/// let json = r#"
431/// {"u": 123, "a": {"b" : {"c": [null, "found"]}}}"#;
432///
433/// // build a pointer tree, representing multiple json path
434/// let mut tree = PointerTree::new();
435///
436/// tree.add_path(&["u"]);
437/// tree.add_path(&["unknown_key"]);
438/// tree.add_path(&pointer!["a", "b", "c", 1]);
439///
440/// let nodes = unsafe { sonic_rs::get_many(json, &tree) };
441///
442/// match nodes {
443///     Ok(vals) => {
444///         assert_eq!(vals[0].as_ref().unwrap().as_raw_str(), "123");
445///         assert!(vals[1].is_none());
446///         assert_eq!(vals[2].as_ref().unwrap().as_raw_str(), "\"found\"");
447///     }
448///     Err(e) => {
449///         panic!("err: {:?}", e)
450///     }
451/// }
452/// ```
453pub fn get_many<'de, Input>(json: Input, tree: &PointerTree) -> Result<Vec<Option<LazyValue<'de>>>>
454where
455    Input: JsonInput<'de>,
456{
457    let slice = json.to_u8_slice();
458    let reader = Read::new(slice, false);
459    let mut parser = Parser::new(reader);
460    let nodes = parser.get_many(tree, true)?;
461
462    // validate the utf-8 if slice
463    let index = parser.read.index();
464    if json.need_utf8_valid() {
465        from_utf8(&slice[..index])?;
466    }
467    Ok(nodes)
468}
469
470#[cfg(test)]
471mod test {
472    use std::str::{from_utf8_unchecked, FromStr};
473
474    use super::*;
475    use crate::{pointer, JsonPointer};
476
477    fn test_get_ok(json: &str, path: &JsonPointer, expect: &str) {
478        // get from str
479        let out = unsafe { get_from_str_unchecked(json, path).unwrap() };
480        assert_eq!(out.as_raw_str(), expect);
481        let out = get_from_str(json, path).unwrap();
482        assert_eq!(out.as_raw_str(), expect);
483
484        // get from slice
485        let out = unsafe { get_from_slice_unchecked(json.as_bytes(), path).unwrap() };
486        assert_eq!(out.as_raw_str(), expect);
487        let out = get_from_slice(json.as_bytes(), path).unwrap();
488        assert_eq!(out.as_raw_str(), expect);
489
490        // get from bytes
491        let bytes = Bytes::copy_from_slice(json.as_bytes());
492        let out = unsafe { get_from_bytes_unchecked(&bytes, path).unwrap() };
493        assert_eq!(out.as_raw_str(), expect);
494        let out = get_from_bytes(&bytes, path).unwrap();
495        assert_eq!(out.as_raw_str(), expect);
496
497        // get from FastStr
498        let fstr = faststr::FastStr::from_str(json).unwrap();
499        let out = unsafe { get_from_faststr_unchecked(&fstr, path).unwrap() };
500        assert_eq!(out.as_raw_str(), expect);
501        let out = get_from_faststr(&fstr, path).unwrap();
502        assert_eq!(out.as_raw_str(), expect);
503
504        // get from traits
505        let out = unsafe { get_unchecked(&fstr, path).unwrap() };
506        assert_eq!(out.as_raw_str(), expect);
507        let out = get(&fstr, path).unwrap();
508        assert_eq!(out.as_raw_str(), expect);
509
510        // test for SIMD codes
511        let json = json.to_string() + &" ".repeat(1000);
512        let out = unsafe { get_unchecked(&json, path).unwrap() };
513        assert_eq!(out.as_raw_str(), expect);
514        let out = get(&json, path).unwrap();
515        assert_eq!(out.as_raw_str(), expect);
516    }
517
518    #[test]
519    fn test_get_from_empty_path() {
520        test_get_ok(r#""""#, &pointer![], r#""""#);
521        test_get_ok(r#"{}"#, &pointer![], r#"{}"#);
522        test_get_ok(r#"[]"#, &pointer![], r#"[]"#);
523        test_get_ok(r#"true"#, &pointer![], r#"true"#);
524        test_get_ok(r#"false"#, &pointer![], r#"false"#);
525        test_get_ok(r#"null"#, &pointer![], r#"null"#);
526    }
527
528    #[test]
529    fn test_get_from_json() {
530        test_get_ok(
531            r#"{"a":"\n\tHello,\nworld!\n"}"#,
532            &pointer!["a"],
533            r#""\n\tHello,\nworld!\n""#,
534        );
535        test_get_ok(
536            r#"{"a":"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"}"#,
537            &pointer!["a"],
538            r#""\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\""#,
539        );
540        test_get_ok(
541            r#"{"":"\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\""}"#,
542            &pointer![""],
543            r#""\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"""#,
544        );
545        test_get_ok("[1, null, 2, 3]", &pointer![], "[1, null, 2, 3]");
546        test_get_ok("[[1], [2, 3], [4, 5, 6]]", &pointer![2, 2], "6");
547        test_get_ok(
548            r#"{"a":{"b":{"c":"hello, world!"}}}"#,
549            &pointer!["a", "b", "c"],
550            r#""hello, world!""#,
551        );
552        test_get_ok(
553            r#"{"a\"":{"b\"":{"c\"":"hello, world!"}}}"#,
554            &pointer!["a\"", "b\"", "c\""],
555            r#""hello, world!""#,
556        );
557    }
558
559    #[test]
560    fn test_get_from_json_with_trailings() {
561        test_get_ok(
562            r#"1230/(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"#,
563            &pointer![],
564            r#"1230"#,
565        );
566    }
567
568    #[test]
569    fn test_get_from_json_failed() {
570        fn test_get_failed(json: &[u8], path: &JsonPointer) {
571            let out = get_from_slice(json, path);
572            assert!(out.is_err(), "json is {:?}", json);
573
574            // test for SIMD codes
575            let json = unsafe { from_utf8_unchecked(json) }.to_string() + &" ".repeat(1000);
576            let out = get_from_slice(json.as_bytes(), path);
577            assert!(out.is_err());
578        }
579
580        test_get_failed(br#"{"a":"\n\tHello,\nworld!\n"}"#, &pointer!["b"]);
581        test_get_failed(br#"{"a":"\n\tHello,\nworld!\n"}"#, &pointer!["a", "b"]);
582        test_get_failed(br#"{"a":"\n\tHello,\nworld!\n"}"#, &pointer!["a", 1]);
583        test_get_failed(br#"{"a": ""invalid", "b":null}"#, &pointer!["a", "b"]);
584        test_get_failed(br#"{"a": "", "b":["123]"}"#, &pointer!["a", "b"]);
585        let data = [b'"', 0x32, 0x32, 0x32, 0x80, 0x90, b'"'];
586        test_get_failed(&data, &pointer![]);
587    }
588
589    #[test]
590    fn test_get_from_json_with_iter() {
591        fn test_str_path(json: &str, path: &[&str], expect: &str) {
592            let out = unsafe { get_unchecked(json, path).unwrap() };
593            assert_eq!(out.as_raw_str(), expect);
594        }
595
596        fn test_faststr_path(json: FastStr, path: &[FastStr], expect: FastStr) {
597            let out = unsafe { get_unchecked(&json, path).unwrap() };
598            assert_eq!(out.as_raw_str(), expect);
599        }
600
601        fn test_index_path(json: &str, path: &[usize], expect: &str) {
602            let out = unsafe { get_unchecked(json, path).unwrap() };
603            assert_eq!(out.as_raw_str(), expect);
604        }
605        test_str_path(
606            r#"{"a":{"b":{"c":"hello, world!"}}}"#,
607            &["a", "b", "c"],
608            r#""hello, world!""#,
609        );
610
611        test_faststr_path(
612            r#"{"a":{"b":{"c":"hello, world!"}}}"#.into(),
613            &["a".into(), "b".into(), "c".into()],
614            r#""hello, world!""#.into(),
615        );
616
617        test_index_path(
618            r#"["a", ["b" , ["c", "hello, world!"]]]"#,
619            &[1, 1, 1],
620            r#""hello, world!""#,
621        );
622    }
623
624    fn build_tree() -> PointerTree {
625        let mut tree = PointerTree::default();
626        tree.add_path(["a", "a_b", "a_b_c"].iter()); // 0
627        tree.add_path(["a", "a_b"].iter()); // 1
628        tree.add_path(pointer!["a", "a_a", 1].iter()); // 2
629        tree.add_path(pointer!["a"].iter()); // 3
630        tree.add_path(pointer!["a"].iter()); // 4
631        tree.add_path(pointer!["b", 2].iter()); // 5
632        tree.add_path(pointer![].iter()); // 6
633        tree.add_path(pointer!["unknown_key"].iter()); // 7
634        assert_eq!(tree.size(), 8);
635        tree
636    }
637
638    #[test]
639    fn test_get_many() {
640        let json = Bytes::from(
641            r#"{
642                "b": [0, 1, true],
643                "a": {
644                    "a_b":{
645                        "a_b_c":"hello, world!"
646                    },
647                    "a_a": [0, 1, 2]
648                }
649            }
650            "#,
651        );
652
653        let tree = build_tree();
654        test_many_ok(unsafe { get_many_unchecked(&json, &tree).unwrap() });
655        test_many_ok(get_many(&json, &tree).unwrap());
656
657        fn test_many_ok(many: Vec<Option<LazyValue<'_>>>) {
658            assert_eq!(many[0].as_ref().unwrap().as_raw_str(), "\"hello, world!\"");
659            assert_eq!(
660                many[1].as_ref().unwrap().as_raw_str(),
661                "{\n                        \"a_b_c\":\"hello, world!\"\n                    }"
662            );
663            assert_eq!(many[2].as_ref().unwrap().as_raw_str(), "1");
664            assert_eq!(many[3].as_ref().unwrap().as_raw_str(), "{\n                    \"a_b\":{\n                        \"a_b_c\":\"hello, world!\"\n                    },\n                    \"a_a\": [0, 1, 2]\n                }");
665            assert_eq!(
666                many[4].as_ref().unwrap().as_raw_str(),
667                many[3].as_ref().unwrap().as_raw_str()
668            );
669            assert_eq!(many[5].as_ref().unwrap().as_raw_str(), "true");
670            // we have strip the leading or trailing spaces
671            assert_eq!(many[6].as_ref().unwrap().as_raw_str(), "{\n                \"b\": [0, 1, true],\n                \"a\": {\n                    \"a_b\":{\n                        \"a_b_c\":\"hello, world!\"\n                    },\n                    \"a_a\": [0, 1, 2]\n                }\n            }");
672            assert!(many[7].is_none())
673        }
674    }
675}