gjson/
lib.rs

1// Copyright 2021 Joshua J Baker. All rights reserved.
2// Use of this source code is governed by an MIT-style
3// license that can be found in the LICENSE file.
4
5mod modifiers;
6mod multipath;
7mod path;
8mod pretty;
9mod test;
10/// Additional tools for working with JSON data.
11pub mod tools;
12mod util;
13mod valid;
14
15use path::*;
16use std::cmp::Ordering;
17use std::fmt;
18use util::{pmatch, tostr, unescape};
19pub use valid::valid;
20
21type InfoBits = u32;
22
23/// The kind of json `Value`.
24#[derive(Copy, Clone, Eq)]
25pub enum Kind {
26    Null,
27    False,
28    Number,
29    String,
30    True,
31    Array,
32    Object,
33}
34
35impl PartialOrd for Kind {
36    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
37        Some(self.cmp(other))
38    }
39}
40
41impl PartialEq for Kind {
42    fn eq(&self, other: &Self) -> bool {
43        self.cmp(&other) == Ordering::Equal
44    }
45}
46
47impl Ord for Kind {
48    fn cmp(&self, other: &Self) -> Ordering {
49        (*self as i32).cmp(&(*other as i32))
50    }
51}
52
53// first eight bits are reserved for json-kind flags
54const INFO_NULL: InfoBits = 1 << 1;
55const INFO_FALSE: InfoBits = 1 << 2;
56const INFO_NUMBER: InfoBits = 1 << 3;
57const INFO_STRING: InfoBits = 1 << 4;
58const INFO_TRUE: InfoBits = 1 << 5;
59const INFO_OBJECT: InfoBits = 1 << 6;
60const INFO_ARRAY: InfoBits = 1 << 7;
61// remaing 8-31 bits used for extra details
62const INFO_ESC: InfoBits = 1 << 8;
63const INFO_SIGN: InfoBits = 1 << 9;
64const INFO_DOT: InfoBits = 1 << 10;
65const INFO_E: InfoBits = 1 << 11;
66const INFO_FOG: InfoBits = 1 << 12;
67
68static KINDMAP: [Kind; 256] = {
69    let mut map = [Kind::Null; 256];
70    map[INFO_NULL as usize] = Kind::Null;
71    map[INFO_FALSE as usize] = Kind::False;
72    map[INFO_NUMBER as usize] = Kind::Number;
73    map[INFO_STRING as usize] = Kind::String;
74    map[INFO_TRUE as usize] = Kind::True;
75    map[INFO_OBJECT as usize] = Kind::Object;
76    map[INFO_ARRAY as usize] = Kind::Array;
77    map
78};
79
80/// Value is the JSON value returned from the `get` function.
81pub struct Value<'a> {
82    slice: &'a str,
83    owned: String,
84    uescstr: String,
85    info: InfoBits,
86    index: Option<usize>,
87}
88
89impl<'a> Eq for Value<'a> {}
90
91impl<'a> PartialOrd for Value<'a> {
92    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
93        Some(self.cmp(other))
94    }
95}
96
97impl<'a> PartialEq for Value<'a> {
98    fn eq(&self, other: &Self) -> bool {
99        self.cmp(&other) == Ordering::Equal
100    }
101}
102
103impl<'a> Ord for Value<'a> {
104    fn cmp(&self, other: &Self) -> Ordering {
105        let cmp = self.kind().cmp(&other.kind());
106        if cmp != Ordering::Equal {
107            cmp
108        } else if self.kind() == Kind::String {
109            self.str().cmp(other.str())
110        } else if self.kind() == Kind::Number {
111            let x = self.f64();
112            let y = other.f64();
113            if x < y {
114                Ordering::Less
115            } else if x > y {
116                Ordering::Greater
117            } else {
118                Ordering::Equal
119            }
120        } else {
121            self.json().cmp(other.json())
122        }
123    }
124}
125
126impl<'a> Default for Value<'a> {
127    fn default() -> Self {
128        return Value {
129            slice: "",
130            owned: String::default(),
131            uescstr: String::default(),
132            info: 0,
133            index: None,
134        };
135    }
136}
137
138impl<'a> fmt::Display for Value<'a> {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        write!(f, "{}", self.str())
141    }
142}
143
144fn json_clone_from_ref<'a>(json: &'a Value<'a>) -> Value<'a> {
145    Value {
146        slice: json.json(),
147        owned: String::new(),
148        uescstr: json.uescstr.to_owned(),
149        info: json.info,
150        index: json.index,
151    }
152}
153
154fn json_from_slice<'a>(slice: &'a [u8], index: Option<usize>, info: InfoBits) -> Value<'a> {
155    let mut json = Value {
156        slice: tostr(slice),
157        owned: String::new(),
158        uescstr: String::new(),
159        info,
160        index,
161    };
162    json_unescape_string(&mut json);
163    return json;
164}
165
166fn json_from_owned<'a>(owned: String, index: Option<usize>, info: InfoBits) -> Value<'a> {
167    let mut json = Value {
168        slice: "",
169        owned: owned,
170        uescstr: String::new(),
171        info,
172        index,
173    };
174    json_unescape_string(&mut json);
175    return json;
176}
177
178fn json_unescape_string<'a>(json: &mut Value<'a>) {
179    if json.info & (INFO_STRING | INFO_ESC) == (INFO_STRING | INFO_ESC) {
180        // Escaped string. We must unescape it into a new allocated string.
181        json.uescstr = unescape(json.json());
182    }
183}
184
185impl<'a> Value<'a> {
186    pub fn get(&'a self, path: &'a str) -> Value<'a> {
187        let mut json = if self.slice.len() > 0 {
188            get(&self.slice, path)
189        } else {
190            json_into_owned(get(&self.owned, path))
191        };
192        let mut index = None;
193        if let Some(index1) = self.index {
194            if let Some(index2) = json.index {
195                index = Some(index1 + index2);
196            }
197        }
198        json.index = index;
199        json
200    }
201
202    pub fn exists(&self) -> bool {
203        self.json().len() > 0
204    }
205
206    pub fn kind(&self) -> Kind {
207        KINDMAP[(self.info << 24 >> 24) as usize]
208    }
209
210    pub fn json(&self) -> &str {
211        if self.owned.len() > 0 {
212            self.owned.as_str()
213        } else {
214            self.slice
215        }
216    }
217
218    pub fn f64(&'a self) -> f64 {
219        let raw = self.json().as_bytes();
220        match self.kind() {
221            Kind::True => 1.0,
222            Kind::String => {
223                if self.info & INFO_ESC == INFO_ESC {
224                    raw_to_f64(&unescape(tostr(raw)))
225                } else {
226                    raw_to_f64(tostr(&raw[1..raw.len() - 1]))
227                }
228            }
229            Kind::Number => raw_to_f64(tostr(raw)),
230            _ => 0.0,
231        }
232    }
233
234    pub fn f32(&'a self) -> f32 {
235        self.f64() as f32
236    }
237
238    pub fn i64(&'a self) -> i64 {
239        let raw = self.json().as_bytes();
240        match self.kind() {
241            Kind::True => 1,
242            Kind::String => {
243                if self.info & INFO_ESC == INFO_ESC {
244                    raw_to_i64(&unescape(tostr(raw)))
245                } else {
246                    raw_to_i64(tostr(&raw[1..raw.len() - 1]))
247                }
248            }
249            Kind::Number => raw_to_i64(tostr(raw)),
250            _ => 0,
251        }
252    }
253
254    pub fn u64(&'a self) -> u64 {
255        let raw = self.json().as_bytes();
256        match self.kind() {
257            Kind::True => 1,
258            Kind::String => {
259                if self.info & INFO_ESC == INFO_ESC {
260                    raw_to_u64(&unescape(tostr(raw)))
261                } else {
262                    raw_to_u64(tostr(&raw[1..raw.len() - 1]))
263                }
264            }
265            Kind::Number => raw_to_u64(tostr(raw)),
266            _ => 0,
267        }
268    }
269
270    pub fn i32(&'a self) -> i32 {
271        let x = self.i64();
272        (if x < -2147483648 {
273            -2147483648
274        } else if x > 2147483648 {
275            2147483648
276        } else {
277            x
278        }) as i32
279    }
280
281    pub fn i16(&'a self) -> i16 {
282        let x = self.i64();
283        (if x < -32768 {
284            -32768
285        } else if x > 32767 {
286            32767
287        } else {
288            x
289        }) as i16
290    }
291
292    pub fn i8(&'a self) -> i8 {
293        let x = self.i64();
294        (if x < -128 {
295            -128
296        } else if x > 127 {
297            127
298        } else {
299            x
300        }) as i8
301    }
302
303    pub fn u32(&'a self) -> u32 {
304        let x = self.u64();
305        (if x > 4294967295 { 4294967295 } else { x }) as u32
306    }
307
308    pub fn u16(&'a self) -> u16 {
309        let x = self.u64();
310        (if x > 65535 { 65535 } else { x }) as u16
311    }
312
313    pub fn u8(&'a self) -> u8 {
314        let x = self.u64();
315        (if x > 255 { 255 } else { x }) as u8
316    }
317
318    pub fn bool(&'a self) -> bool {
319        let raw = self.json();
320        match raw {
321            r#"1"# | r#"true"# => true,
322            r#"0"# | r#"false"# => false,
323
324            r#""t""# | r#""1""# | r#""T""# => true,
325            r#""f""# | r#""0""# | r#""F""# => false,
326
327            r#""true""# | r#""TRUE""# | r#""True""# => true,
328            r#""false""# | r#""FALSE""# | r#""False""# => false,
329            _ => self.i64() != 0,
330        }
331    }
332
333    pub fn str(&'a self) -> &'a str {
334        match self.kind() {
335            Kind::True => "true",
336            Kind::False => "false",
337            Kind::Object | Kind::Array | Kind::Number => self.json(),
338            Kind::String => {
339                if self.info & INFO_ESC == INFO_ESC {
340                    self.uescstr.as_ref()
341                } else {
342                    let raw = self.json().as_bytes();
343                    tostr(&raw[1..raw.len() - 1])
344                }
345            }
346            // Return an empty string for null. Use raw() to return the
347            // raw json.
348            Kind::Null => "",
349        }
350    }
351
352    pub fn each(&'a self, mut iter: impl FnMut(Value<'a>, Value<'a>) -> bool) {
353        if !self.exists() {
354            return;
355        }
356        let kind = self.kind();
357        if kind != Kind::Object && kind != Kind::Array {
358            iter(Value::default(), json_clone_from_ref(&self));
359            return;
360        }
361        let json = self.json().as_bytes();
362        for_each(json, 0, false, kind, iter);
363    }
364
365    pub fn array(&'a self) -> Vec<Value<'a>> {
366        let mut arr = Vec::new();
367        if self.kind() == Kind::Array {
368            self.each(|_, value| {
369                arr.push(value);
370                true
371            })
372        }
373        arr
374    }
375}
376
377fn for_each<'a>(
378    json: &'a [u8],
379    mut i: usize,
380    lines: bool,
381    kind: Kind,
382    mut iter: impl FnMut(Value<'a>, Value<'a>) -> bool,
383) -> usize {
384    if i == json.len() {
385        return i;
386    }
387    if !lines {
388        i += 1;
389    }
390    let mut index = 0;
391    let mut tmp_key = Value::default();
392    while i < json.len() {
393        if json[i] <= b' ' || json[i] == b',' || json[i] == b':' {
394            i += 1;
395            continue;
396        }
397        if json[i] == b'}' || json[i] == b']' {
398            return i + 1;
399        }
400        let (res, next_i, _) = proc_value(json, i, Path::default(), true);
401        i = next_i;
402        if res.exists() {
403            if kind == Kind::Object {
404                if index % 2 == 0 {
405                    tmp_key = res;
406                } else {
407                    let key = tmp_key;
408                    tmp_key = Value::default();
409                    if !iter(key, res) {
410                        break;
411                    }
412                }
413            } else {
414                if !iter(Value::default(), res) {
415                    break;
416                }
417            }
418            index += 1;
419        }
420    }
421    i
422}
423
424fn raw_to_f64(raw: &str) -> f64 {
425    raw.parse().unwrap_or(0.0)
426}
427
428fn raw_to_i64(raw: &str) -> i64 {
429    raw.parse().unwrap_or(raw_to_f64(raw) as i64)
430}
431
432fn raw_to_u64(raw: &str) -> u64 {
433    raw.parse().unwrap_or(raw_to_f64(raw) as u64)
434}
435
436const CHQUOTE: u8 = 1 << 1;
437const CHOPEN: u8 = 1 << 2;
438const CHCLOSE: u8 = 1 << 3;
439const CHSTRTOK: u8 = 1 << 4;
440const CHSQUASH: u8 = 1 << 5;
441
442static CHTABLE: [u8; 256] = {
443    let mut table = [0; 256];
444    table[b'{' as usize] |= CHSQUASH | CHOPEN;
445    table[b'[' as usize] |= CHSQUASH | CHOPEN;
446    table[b'(' as usize] |= CHSQUASH | CHOPEN;
447    table[b'}' as usize] |= CHSQUASH | CHCLOSE;
448    table[b']' as usize] |= CHSQUASH | CHCLOSE;
449    table[b')' as usize] |= CHSQUASH | CHCLOSE;
450    table[b'"' as usize] |= CHSQUASH | CHQUOTE;
451    table[b'\\' as usize] |= CHSQUASH;
452    table[b'"' as usize] |= CHSTRTOK;
453    table[b'\\' as usize] |= CHSTRTOK;
454    table
455};
456
457// -> (val, info, next_i)
458fn scan_number<'a>(json: &'a [u8], mut i: usize) -> (&'a [u8], InfoBits, usize) {
459    let s = i;
460    let mut info = 0;
461    if json[i] == b'-' {
462        info |= INFO_SIGN;
463    }
464    i += 1;
465    while i < json.len() {
466        let ch = json[i];
467        if ch == b'.' {
468            info |= INFO_DOT;
469        } else if ch == b'e' || ch == b'E' {
470            info |= INFO_E;
471        } else if (ch < b'0' || ch > b'9') && ch != b'-' && ch != b'+' {
472            break;
473        }
474        i += 1;
475    }
476    (&json[s..i], info, i)
477}
478
479#[inline(always)]
480fn scan_string<'a>(json: &'a [u8], mut i: usize) -> (&'a [u8], InfoBits, usize) {
481    let mut info = 0;
482    let s = i;
483    i += 1;
484    'outer: loop {
485        let mut ch;
486        'tok: loop {
487            while i + 8 < json.len() {
488                for _ in 0..8 {
489                    // SAFETY: bounds already checked.
490                    ch = unsafe { *json.get_unchecked(i) } as usize;
491                    if CHTABLE[ch] & CHSTRTOK == CHSTRTOK {
492                        break 'tok;
493                    }
494                    i += 1;
495                }
496            }
497            while i < json.len() {
498                ch = json[i] as usize;
499                if CHTABLE[ch] & CHSTRTOK == CHSTRTOK {
500                    break 'tok;
501                }
502                i += 1;
503            }
504            break 'outer;
505        }
506        if ch as u8 == b'"' {
507            i += 1;
508            return (&json[s..i], info, i);
509        } else {
510            // must be a escape character '\'
511            info |= INFO_ESC;
512            i += 1;
513            if i == json.len() {
514                break;
515            }
516            i += 1;
517        }
518    }
519    ("".as_bytes(), 0, json.len())
520}
521
522// -> (val, next_i)
523fn scan_squash<'a>(json: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
524    let s = i;
525    i += 1;
526    let mut depth = 1;
527    'outer: loop {
528        let mut ch;
529        'tok: loop {
530            while i + 8 < json.len() {
531                for _ in 0..8 {
532                    // SAFETY: bounds already checked.
533                    ch = unsafe { *json.get_unchecked(i) } as usize;
534                    if CHTABLE[ch] & CHSQUASH == CHSQUASH {
535                        break 'tok;
536                    }
537                    i += 1;
538                }
539            }
540            while i < json.len() {
541                ch = json[i] as usize;
542                if CHTABLE[ch] & CHSQUASH == CHSQUASH {
543                    break 'tok;
544                }
545                i += 1;
546            }
547            break 'outer;
548        }
549        if ch as u8 == b'"' {
550            i = scan_string(json, i).2;
551            continue;
552        } else if CHTABLE[ch] & CHOPEN == CHOPEN {
553            depth += 1;
554        } else if CHTABLE[ch] & CHCLOSE == CHCLOSE {
555            depth -= 1;
556            if depth == 0 {
557                i += 1;
558                return (&json[s..i], i);
559            }
560        } else if ch == b'\\' as usize {
561            i += 1;
562            if i == json.len() {
563                break 'outer;
564            }
565        }
566        i += 1;
567    }
568    ("".as_bytes(), json.len())
569}
570
571fn proc_value<'a>(
572    json: &'a [u8],
573    mut i: usize,
574    path: Path<'a>,
575    is_match: bool,
576) -> (Value<'a>, usize, Path<'a>) {
577    if json[i] == b'"' {
578        let s = i;
579        let (val, info, next_i) = scan_string(json, i);
580        i = next_i;
581        if is_match {
582            return (json_from_slice(val, Some(s), info | INFO_STRING), i, path);
583        }
584    } else if json[i] == b'{' || json[i] == b'[' {
585        if is_match {
586            let mut squash = true;
587            if path.sep == b'.' {
588                let next_path = path.next();
589                if !next_path.is_modifier() && !next_path.is_multipath() {
590                    squash = false;
591                    let (res, next_i, next_path) = if json[i] == b'{' {
592                        get_obj(json, i, next_path)
593                    } else {
594                        get_arr(json, i, false, next_path)
595                    };
596                    if res.exists() {
597                        return (res, next_i, next_path);
598                    }
599                }
600            }
601            if squash {
602                // returns the squashed (entire) json value
603                let s = i;
604                let (val, next_i) = scan_squash(json, i);
605                i = next_i;
606                let kind = if json[s] == b'{' {
607                    INFO_OBJECT
608                } else {
609                    INFO_ARRAY
610                };
611                return (json_from_slice(val, Some(s), 0 | kind), i, path);
612            }
613        } else {
614            i = scan_squash(json, i).1;
615        }
616    } else if (json[i] >= b'0' && json[i] <= b'9') || json[i] == b'-' {
617        let s = i;
618        let (val, info, next_i) = scan_number(json, i);
619        i = next_i;
620        if is_match {
621            return (json_from_slice(val, Some(s), info | INFO_NUMBER), i, path);
622        }
623    } else {
624        let s = i;
625        let kind;
626        if json[i] == b't' {
627            if i + 3 >= json.len() {
628                return (Value::default(), json.len(), path);
629            }
630            i += 4;
631            kind = INFO_TRUE;
632        } else if json[i] == b'f' {
633            if i + 4 >= json.len() {
634                return (Value::default(), json.len(), path);
635            }
636            i += 5;
637            kind = INFO_FALSE;
638        } else if json[i] == b'n' {
639            if i + 3 >= json.len() {
640                return (Value::default(), json.len(), path);
641            }
642            i += 4;
643            kind = INFO_NULL;
644        } else {
645            // unknown character
646            return (Value::default(), json.len(), Path::default());
647        }
648        if is_match {
649            return (json_from_slice(&json[s..i], Some(s), kind), i, path);
650        }
651    }
652    (Value::default(), i, path)
653}
654
655fn get_obj<'a>(json: &'a [u8], mut i: usize, path: Path<'a>) -> (Value<'a>, usize, Path<'a>) {
656    if i == json.len() || json[i] != b'{' {
657        return (Value::default(), i, path);
658    }
659    i += 1;
660    while i < json.len() {
661        if json[i] == b'}' {
662            i += 1;
663            break;
664        }
665        if json[i] != b'"' {
666            i += 1;
667            continue;
668        }
669        // key
670        let (key, info, next_i) = scan_string(json, i);
671        i = next_i;
672        while i < json.len() {
673            if json[i] <= b' ' || json[i] == b':' {
674                i += 1;
675                continue;
676            }
677            break;
678        }
679        if i == json.len() {
680            break;
681        }
682        let is_match = key_match(key, info, &path);
683        let (res, next_i, next_path) = proc_value(json, i, path, is_match);
684        i = next_i;
685        if res.exists() {
686            return (res, i, next_path);
687        }
688    }
689    (Value::default(), i, path)
690}
691
692fn key_match(key: &[u8], info: InfoBits, path: &Path) -> bool {
693    let comp = tostr(path.comp);
694    if info & INFO_ESC == INFO_ESC {
695        let key = unescape(tostr(key));
696        if path.pat || path.esc {
697            pmatch(comp, key)
698        } else {
699            key.eq(comp)
700        }
701    } else {
702        let key = tostr(&key[1..key.len() - 1]);
703        if path.pat || path.esc {
704            pmatch(comp, key)
705        } else {
706            key.eq(comp)
707        }
708    }
709}
710
711fn get_arr<'a>(
712    json: &'a [u8],
713    i: usize,
714    lines: bool,
715    path: Path<'a>,
716) -> (Value<'a>, usize, Path<'a>) {
717    // Array paths are special.
718    // There are a few different ways to handling arrays:
719    // - By Index: Return a single child at a specified index.
720    // - Count: Return a count of all children.
721    // - Query: Return a single child using a query.
722    // - Sub path (recomposition): Creates a new array from child paths.
723    // - Query + Sub path (recomp): Create a new array from child querys.
724    // The `lines` param allows for the input to be in JSON Lines format,
725    // where, rather than having [value1,value2,value3], each value is on
726    // a separate line like:
727    // ```
728    // value1
729    // value2
730    // value3
731    // ```
732    if path.comp.len() > 0 && path.comp[0] == b'#' {
733        if path.comp.len() == 1 {
734            if path.sep == b'.' {
735                get_arr_children_with_subpath(json, i, lines, path)
736            } else {
737                get_arr_count(json, i, lines, path)
738            }
739        } else if path.comp[path.comp.len() - 1] == b'#' {
740            get_arr_children_with_query_subpath(json, i, lines, path)
741        } else {
742            get_arr_child_with_query(json, i, lines, path)
743        }
744    } else {
745        get_arr_child_at_index(json, i, lines, path)
746    }
747}
748
749fn get_arr_count<'a>(
750    json: &'a [u8],
751    mut i: usize,
752    lines: bool,
753    path: Path<'a>,
754) -> (Value<'a>, usize, Path<'a>) {
755    let mut count = 0;
756    i = for_each(json, i, lines, Kind::Array, |_, _| {
757        count += 1;
758        true
759    });
760    let res = json_from_owned(format!("{}", count), None, INFO_NUMBER);
761    (res, i, path)
762}
763
764fn get_arr_child_at_index<'a>(
765    json: &'a [u8],
766    mut i: usize,
767    lines: bool,
768    path: Path<'a>,
769) -> (Value<'a>, usize, Path<'a>) {
770    let comp_index = tostr(path.comp).parse::<i64>().unwrap_or(-1);
771    let mut res = Value::default();
772    let mut index = 0;
773    let mut next_i = 0;
774    i = for_each(json, i, lines, Kind::Array, |_, value| {
775        if index == comp_index {
776            res = value;
777            next_i = i;
778            return false;
779        }
780        index += 1;
781        true
782    });
783    if res.exists() {
784        (res, next_i, path)
785    } else {
786        (Value::default(), i, path)
787    }
788}
789
790fn query_matches<'a>(valin: &Value<'a>, op: &str, rpv: &str) -> bool {
791    let uesc_str: String;
792    let mut rpv = rpv.as_bytes();
793    if rpv.len() > 2 && rpv[0] == b'"' && rpv[rpv.len() - 1] == b'"' {
794        let mut overwrite = false;
795        for c in rpv {
796            if *c == b'\\' {
797                overwrite = true;
798                uesc_str = unescape(tostr(rpv));
799                rpv = uesc_str.as_bytes();
800                break;
801            }
802        }
803        if !overwrite {
804            rpv = &rpv[1..rpv.len() - 1];
805        }
806    }
807    let mut value = valin;
808    let mut tvalue = Value::default();
809    if rpv.len() > 0 && rpv[0] == b'~' {
810        // convert to bool
811        rpv = &rpv[1..];
812        if value.bool() {
813            tvalue.slice = "true";
814            tvalue.info = INFO_TRUE;
815        } else {
816            tvalue.slice = "false";
817            tvalue.info = INFO_FALSE;
818        }
819        value = &tvalue;
820    }
821    let rpv = tostr(rpv);
822    if !value.exists() {
823        return false;
824    }
825    if op == "" {
826        // the query is only looking for existence, such as:
827        //   friends.#(name)
828        // which makes sure that the array "friends" has an element of
829        // "name" that exists
830        return true;
831    }
832    match value.kind() {
833        Kind::String => match op {
834            "=" => value.str() == rpv,
835            "!=" => value.str() != rpv,
836            "<" => value.str() < rpv,
837            "<=" => value.str() <= rpv,
838            ">" => value.str() > rpv,
839            ">=" => value.str() >= rpv,
840            "%" => pmatch(rpv, value.str()),
841            "!%" => !pmatch(rpv, value.str()),
842            _ => false,
843        },
844        Kind::Number => {
845            let rpvn = rpv.parse().unwrap_or(0.0);
846            match op {
847                "=" => value.f64() == rpvn,
848                "!=" => value.f64() != rpvn,
849                "<" => value.f64() < rpvn,
850                "<=" => value.f64() <= rpvn,
851                ">" => value.f64() > rpvn,
852                ">=" => value.f64() >= rpvn,
853                _ => false,
854            }
855        }
856        Kind::True => match op {
857            "=" => rpv == "true",
858            "!=" => rpv != "true",
859            ">" => rpv == "false",
860            ">=" => true,
861            _ => false,
862        },
863        Kind::False => match op {
864            "=" => rpv == "false",
865            "!=" => rpv != "false",
866            "<" => rpv == "true",
867            "<=" => true,
868            _ => false,
869        },
870        _ => false,
871    }
872}
873
874fn get_arr_child_with_query<'a>(
875    json: &'a [u8],
876    mut i: usize,
877    lines: bool,
878    path: Path<'a>,
879) -> (Value<'a>, usize, Path<'a>) {
880    let (lh, op, rhv) = path.query_parts();
881    let mut res = Value::default();
882    i = for_each(json, i, lines, Kind::Array, |_, value| {
883        let is_match = if lh != "" {
884            query_matches(&value.get(lh), op, rhv)
885        } else {
886            query_matches(&value, op, rhv)
887        };
888        if is_match {
889            res = value;
890            return false;
891        }
892        true
893    });
894    if res.exists() {
895        (res, i, path)
896    } else {
897        (Value::default(), i, path)
898    }
899}
900
901fn get_arr_children_with_query_subpath<'a>(
902    json: &'a [u8],
903    mut i: usize,
904    lines: bool,
905    mut path: Path<'a>,
906) -> (Value<'a>, usize, Path<'a>) {
907    let (lh, op, rhv) = path.query_parts();
908    let mut subpath = None;
909    let r = path.next_group();
910    if path.sep == b'.' {
911        subpath = Some(r.0);
912    }
913    path = r.1;
914    let mut res = Vec::new();
915    res.push(b'[');
916    let mut index = 0;
917    i = for_each(json, i, lines, Kind::Array, |_, value| {
918        let is_match = if lh != "" {
919            query_matches(&value.get(lh), op, rhv)
920        } else {
921            query_matches(&value, op, rhv)
922        };
923        if is_match {
924            let value = if let Some(subpath) = subpath {
925                value.get(subpath)
926            } else {
927                value
928            };
929            if value.exists() {
930                if index > 0 {
931                    res.push(b',');
932                }
933                res.extend(value.json().as_bytes());
934                index += 1;
935            }
936        }
937        true
938    });
939    res.push(b']');
940    let res = json_from_owned(
941        // SAFETY: buffer was constructed from known utf8 parts.
942        unsafe { String::from_utf8_unchecked(res) },
943        None,
944        INFO_ARRAY,
945    );
946    (res, i, path)
947}
948
949fn get_arr_children_with_subpath<'a>(
950    json: &'a [u8],
951    mut i: usize,
952    lines: bool,
953    mut path: Path<'a>,
954) -> (Value<'a>, usize, Path<'a>) {
955    let r = path.next_group();
956    let subpath = r.0;
957    path = r.1;
958    let mut res = Vec::new();
959    res.push(b'[');
960    let mut index = 0;
961    i = for_each(json, i, lines, Kind::Array, |_, value| {
962        let value = value.get(subpath);
963        if value.exists() {
964            if index > 0 {
965                res.push(b',');
966            }
967            res.extend(value.json().as_bytes());
968            index += 1;
969        }
970        true
971    });
972    res.push(b']');
973    let res = json_from_owned(
974        // SAFETY: buffer was constructed from known utf8 parts.
975        unsafe { String::from_utf8_unchecked(res) },
976        None,
977        INFO_ARRAY,
978    );
979    (res, i, path)
980}
981
982/// Searches json for the specified path.
983/// A path is in dot syntax, such as "name.last" or "age".
984/// When the value is found it's returned immediately.
985///
986/// A path is a series of keys separated by a dot.
987/// A key may contain special wildcard characters '*' and '?'.
988/// To access an array value use the index as the key.
989/// To get the number of elements in an array or to access a child path, use
990/// the '#' character.
991/// The dot and wildcard character can be escaped with '\'.
992///
993/// ```json
994/// {
995///   "name": {"first": "Tom", "last": "Anderson"},
996///   "age":37,
997///   "children": ["Sara","Alex","Jack"],
998///   "friends": [
999///     {"first": "James", "last": "Murphy"},
1000///     {"first": "Roger", "last": "Craig"}
1001///   ]
1002/// }
1003/// ```
1004///
1005/// ```json
1006///  "name.last"          >> "Anderson"
1007///  "age"                >> 37
1008///  "children"           >> ["Sara","Alex","Jack"]
1009///  "children.#"         >> 3
1010///  "children.1"         >> "Alex"
1011///  "child*.2"           >> "Jack"
1012///  "c?ildren.0"         >> "Sara"
1013///  "friends.#.first"    >> ["James","Roger"]
1014/// ```
1015///
1016/// This function expects that the json is valid, and does not validate.
1017/// Invalid json will not panic, but it may return back unexpected results.
1018/// If you are consuming JSON from an unpredictable source then you may want to
1019/// use the `valid` function first.
1020#[inline]
1021pub fn get<'a>(json: &'a str, path: &'a str) -> Value<'a> {
1022    let mut path = path;
1023    let mut lines = false;
1024    if path.len() >= 2 && path.as_bytes()[0] == b'.' && path.as_bytes()[1] == b'.' {
1025        // json lines
1026        path = tostr(&path.as_bytes()[2..]);
1027        lines = true;
1028    }
1029    let path = Path::new(path);
1030    let (res, path) = {
1031        let json = json.as_bytes();
1032        if lines {
1033            let res = get_arr(json, 0, true, path);
1034            (res.0, res.2)
1035        } else if path.is_modifier() {
1036            modifiers::exec(json, path)
1037        } else if path.is_multipath() {
1038            multipath::exec(json, path)
1039        } else {
1040            let mut i = 0;
1041            loop {
1042                if i == json.len() {
1043                    break (Value::default(), path);
1044                }
1045                if json[i] <= b' ' {
1046                    i += 1;
1047                    continue;
1048                }
1049                if json[i] == b'{' {
1050                    let res = get_obj(json, i, path);
1051                    break (res.0, res.2);
1052                }
1053                if json[i] == b'[' {
1054                    let res = get_arr(json, i, false, path);
1055                    break (res.0, res.2);
1056                }
1057                break (Value::default(), path);
1058            }
1059        }
1060    };
1061    if !path.more() {
1062        return res;
1063    }
1064    let path = tostr(path.extra);
1065    let mut json = if res.slice.len() > 0 {
1066        get(&res.slice, path)
1067    } else {
1068        json_into_owned(get(&res.owned, path))
1069    };
1070    let mut index = None;
1071    if let Some(index1) = res.index {
1072        if let Some(index2) = json.index {
1073            index = Some(index1 + index2);
1074        }
1075    }
1076    json.index = index;
1077    json
1078}
1079
1080/// Searches json for the specified path.
1081/// Works the same as `get` except that the input json is a a byte slice
1082/// instead of a string.
1083/// 
1084/// # Safety
1085///
1086/// This function is unsafe because it does not check that the bytes passed to
1087/// it are valid UTF-8. If this constraint is violated, undefined behavior
1088/// results, as the rest of Rust assumes that [`&str`]s in Value<'a> are
1089/// valid UTF-8.
1090pub unsafe fn get_bytes<'a>(json: &'a [u8], path: &'a str) -> Value<'a> {
1091    return get(tostr(json), path)
1092}
1093
1094fn json_into_owned<'a>(json: Value) -> Value<'a> {
1095    Value {
1096        slice: "",
1097        owned: if json.slice.len() > 0 {
1098            json.slice.to_owned()
1099        } else {
1100            json.owned
1101        },
1102        uescstr: json.uescstr,
1103        info: json.info,
1104        index: json.index,
1105    }
1106}
1107
1108/// Parse the json and return it as a value.
1109///
1110/// This function expects that the json is valid, and does not validate.
1111/// Invalid json will not panic, but it may return back unexpected results.
1112/// If you are consuming JSON from an unpredictable source then you may want to
1113/// use the `valid` function first.
1114pub fn parse<'a>(json: &'a str) -> Value<'a> {
1115    let json = json.as_bytes();
1116    let mut i = 0;
1117    while i < json.len() {
1118        if json[i] <= b' ' {
1119            i += 1;
1120            continue;
1121        }
1122        match json[i] {
1123            b'{' => return json_from_slice(&json[i..], Some(i), INFO_OBJECT | INFO_FOG),
1124            b'[' => return json_from_slice(&json[i..], Some(i), INFO_ARRAY | INFO_FOG),
1125            b't' | b'f' | b'n' | b'"' | b'0' | b'1' | b'2' => {}
1126            b'3' | b'4' | b'5' | b'6' | b'7' | b'8' | b'9' | b'-' => {}
1127            _ => break,
1128        }
1129        return proc_value(json, i, Path::default(), true).0;
1130    }
1131    return Value::default();
1132}