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