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}