json_walker/
parser_core.rs

1use std::collections::BTreeMap;
2use std::fmt::{Display, Formatter, Write};
3use std::rc::Rc;
4
5use crate::*;
6
7const NULL: &[u8] = "null".as_bytes();
8const TRUE: &[u8] = "true".as_bytes();
9const FALSE: &[u8] = "false".as_bytes();
10
11//region FixedSizeArray
12struct FixedSizeArray {
13    capacity: usize,
14    pos: usize,
15    arr: Vec<u8>,
16}
17
18impl FixedSizeArray {
19    fn new(capacity: usize) -> Self {
20        let mut a = Vec::with_capacity(capacity);
21        for _ in 0..capacity {
22            a.push(b' ');
23        }
24        FixedSizeArray {
25            pos: 0,
26            capacity,
27            arr: a,
28        }
29    }
30
31    fn push(&mut self, byte: u8) {
32        self.pos = (self.pos + 1) % self.capacity;
33        self.arr[self.pos] = byte;
34    }
35}
36
37impl Display for FixedSizeArray {
38    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
39        let mut container = Vec::with_capacity(self.capacity);
40        let s = self.pos + 1;
41        for i in s..self.capacity { container.push(self.arr[i]); }
42        for i in 0..s { container.push(self.arr[i]); }
43        f.write_str(&String::from_utf8_lossy(&container))
44    }
45}
46//endregion
47
48//region pubs including Parser, Content, PathItem, ValueType
49pub struct Parser {
50    reader: Box<dyn Iterator<Item=u8>>,
51    pub next_byte: u8,
52    txt: FixedSizeArray,
53    next_fn: fn(&mut Parser) -> u8,
54    pub stack: Vec<StackItem>,
55}
56
57impl Parser {
58    /// To read
59    /// **reader** is the mechanism to access bytes of the json
60    /// **mem_size** determines the size of a buffer which is responsible to hold a copy of most recent bytes, so there would be an extra u8 copy operation.
61    /// If you need to preview the most recent piece of json, set mem_size as you wish. Then you can access that by calling get_recent_piece()
62    /// ### Example
63    /// ```
64    /// use json_walker::json_walker::{JsonWalker, StringReader};
65    ///
66    /// fn main() {
67    ///     let mut walker = JsonWalker::new(StringReader::new(r#"{"key":"value"}"#.to_string()), 50);
68    ///     loop {
69    ///         match walker.next_item() {
70    ///             Ok(t) => { println!("{t:?}") }
71    ///             Err(_) => { break; }
72    ///         }
73    ///     }
74    /// }
75    /// ```
76    pub fn new(reader: Box<dyn Iterator<Item=u8>>, mem_size: usize) -> Self {
77        let mut stack = Vec::with_capacity(30);
78        stack.push(new_colon_stack_item(Rc::new(String::from(ROOT)), -0.5));
79
80        let txt: FixedSizeArray;
81        let next_fn: fn(&mut Parser) -> u8;
82
83        if mem_size > 0 {
84            txt = FixedSizeArray::new(mem_size);
85            next_fn = next_byte_with_memory;
86        } else {
87            txt = FixedSizeArray::new(1);
88            next_fn = next_byte;
89        }
90
91        let mut h = Parser {
92            reader,
93            next_byte: NIL,
94            txt,
95            next_fn,
96            stack,
97        };
98        next_no_white_space(&mut h);
99        h
100    }
101}
102
103pub type Item = (ValueType, String);
104
105#[derive(Debug, PartialEq)]
106pub enum Content {
107    Simple(Item),
108    Array(Vec<Content>),
109    Object(BTreeMap<String, Content>),
110}
111
112#[derive(Debug)]
113pub enum PathItem {
114    Start,
115    Object(Rc<String>, usize),
116    Array(Rc<String>, usize),
117}
118
119impl Display for PathItem {
120    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
121        match self {
122            PathItem::Start => f.write_char(ROOT),
123            PathItem::Object(s, i) => f.write_str(&format!("{}{},{}{}", '{', s, i, '}')),
124            PathItem::Array(s, i) => f.write_str(&format!("{}{},{}{}", '[', s, i, ']')),
125        }
126    }
127}
128
129#[derive(Debug, PartialEq, Copy, Clone)]
130pub enum ValueType {
131    Null,
132    Bool,
133    Int,
134    Float,
135    Str,
136    Arr,
137    Obj,
138}
139//endregion
140
141//region Parser controller methods such as next(), error report builder,...
142
143/// when reader returns None, this function gets called
144fn on_none_input(parser: &mut Parser) -> u8 {
145    if parser.stack.len() > 2 {
146        panic!(r#"Unexpected end of stream"#)
147    }
148    NIL
149}
150
151/// call this function when memory size is zero
152fn next_byte(parser: &mut Parser) -> u8 {
153    parser
154        .reader
155        .next()
156        .unwrap_or_else(|| on_none_input(parser))
157}
158
159/// call this function when memory is set
160fn next_byte_with_memory(parser: &mut Parser) -> u8 {
161    match parser
162        .reader
163        .next() {
164        None => on_none_input(parser),
165        Some(b) => {
166            parser.txt.push(b);
167            b
168        }
169    }
170}
171
172/// return next byte from the reader. No matter if that byte is white-space or not
173fn next(parser: &mut Parser) -> u8 {
174    // strings start with " and finish with ". so from the iterator view point, it is clear to find out the start and end point.
175    // null, true & false are key words and the length of them are fix, so the start and end points are obvious
176    // but when it comes to reading numbers, from the iterator aspect view,
177    // there is no way to find out when digits finish and it always needs to read bytes till one none digit byte,
178    // but that byte is going to be processed in the next loop and we have consume it early.
179    // The way to solve that is to walk one byte backward, but iterator does not support that,
180    // so it would be better to read a byte and save it for next loop, then process one byte ago.
181    // this is why, I am using next_byte. also it comes handy when I want to find out if the stream is finished.
182    let c = parser.next_byte;
183    parser.next_byte = (parser.next_fn)(parser);
184    c
185}
186
187/// return next none white-space byte
188fn next_no_white_space(parser: &mut Parser) -> u8 {
189    let c = parser.next_byte;
190    loop {
191        parser.next_byte = (parser.next_fn)(parser);
192        if !parser.next_byte.is_ascii_whitespace() {
193            break;
194        }
195    }
196    c
197}
198
199/// get current stack status including latest_key, node level, stack top char, nth occurrence and recent piece of json if memory size is set
200pub fn get_current_status(parser: &mut Parser) -> String {
201    let t = parser.txt.to_string();
202    let l = t.len() - 1;
203    if let Some(a) = parser.stack.last() {
204        let level = a.level;
205        let stack_top = a.symbol;
206        let key = format!(r#""{}""#, a.key.clone());
207        let nth = a.nth;
208        format!("level: {level:<5}, key: {key:<20}, top: '{stack_top}',  nth: {nth:<4},\t\t\x1b[91m{}\x1b[32m{}\x1b[0m{}...", &t[0..l], &t[l..l + 1], &t[l + 1..])
209    } else {
210        "stack is empty".to_string()
211    }
212}
213/// convert utf8 bytes to string and panic if its not standard utf8 string
214fn to_string(v: Vec<u8>) -> String {
215    String::from_utf8(v).expect("This input is not utf8 formatted string")
216}
217
218/// return stock top index and check stack size and panic if necessary
219pub fn get_stack_top_index(parser: &mut Parser) -> usize {
220    let l = parser.stack.len();
221    if l == 0 {
222        panic!(
223            "The json string is malformed. Json is closed while there are more data. {}",
224            get_current_status(parser)
225        )
226    }
227    l - 1
228}
229
230/// Parse json stream. Verification happens during parsing, so the stream can be incomplete.
231/// The result may be a key, value or None
232///
233/// ### Sample result
234/// <pre>
235/// None({ as u8)    (String,"key")    None(: as u8)     (Integer,"123")    None({ as u8)
236/// <span style="color:yellow">
237/// ↓                    ↓              ↓                       ↓             ↓
238/// </span>
239/// {                  "key"            :                      123            }
240/// </pre>
241pub fn walk_forward(parser: &mut Parser) -> TextItem {
242    let c = next_no_white_space(parser);
243    let top_index = get_stack_top_index(parser);
244    (parser.stack[top_index].next_executor)(parser, top_index, c)
245}
246
247/// return the level of current position in json string.
248/// for more information check out next_item_by_level() doc
249pub fn get_current_level(parser: &Parser) -> f32 {
250    match parser.stack.last() {
251        None => { -1.0 }
252        Some(t) => { t.level }
253    }
254}
255
256/// Parse json until the position at which, node level reaches the target_level_offset
257/// ## Sample json with level in different positions after parsing each element:
258/// <pre>
259/// <span style="color:red">
260/// 0 1       1 1.5   1  1       1 1.5 2     2  2  3        3 3.5   3  2  1  0
261/// </span>
262/// <span style="color:yellow">
263/// ↓ ↓       ↓  ↓    ↓  ↓       ↓  ↓  ↓     ↓  ↓  ↓        ↓  ↓    ↓  ↓  ↓  ↓
264/// </span>
265///  {  "key1"  :  123  ,  "key2"  :  [  true  ,  {  "key21"  :  2.5  }  ]  }
266/// </pre>
267///
268/// The result determines if there can be more data or not.
269/// For example if cursor is the above json is after 2.5 and before "}", result will be false. It means that there is no more data for level 3.
270pub fn seek_by_level_offset(parser: &mut Parser, target_level_offset: f32) -> bool {
271    let mut top_index = get_stack_top_index(parser);
272    let target_level = parser.stack[top_index].level + target_level_offset;
273
274    // there is no item in level 0 (except root) and smaller than that
275    if target_level < 1_f32 { return false; };
276
277    while parser.next_byte != NIL {
278        walk_forward(parser);
279        top_index = parser.stack.len() - 1;
280        if parser.stack[top_index].level == target_level /*&& parser.next_byte != b','*/ {
281            return parser.next_byte != b'}' && parser.next_byte != b']';
282        }
283    }
284    false
285}
286
287/// if mem_size is set in new() function, this function will return the latest piece of json, so you can apply a regex operation for example
288pub fn get_recent_piece(parser: &mut Parser) -> String {
289    parser.txt.to_string()
290}
291//endregion
292
293//region extractors
294
295/// extract data between two "
296fn extract_string(parser: &mut Parser) -> Item {
297    let mut result = Vec::with_capacity(50);
298    let mut c: u8;
299    loop {
300        c = next(parser);
301        if c == b'\\' {
302            c = next(parser);
303        } else if c == b'"' {
304            break;
305        }
306        result.push(c);
307    }
308    if parser.next_byte.is_ascii_whitespace() {
309        next_no_white_space(parser);
310    }
311    (ValueType::Str, to_string(result))
312}
313
314/// extract some data such as null, true, false and numbers
315fn extract_word(parser: &mut Parser, mut c: u8) -> Item {
316    let mut result = Vec::with_capacity(50);
317    let value_type;
318    let mut d: usize;
319    if c == b'+' || c == b'-' || c.is_ascii_digit() {
320        result.push(c);
321        d = 0;
322        let mut last_digit_index = if c != b'+' && c != b'-' { 1 } else { usize::MAX };
323        loop {
324            c = parser.next_byte;
325            if c == b'.' {
326                if d >= 1 {
327                    panic!(
328                        r#"It is not allowed to have more than one point in a number.{}"#,
329                        get_current_status(parser)
330                    );
331                }
332                d += 1;
333                result.push(c);
334                _ = next(parser);
335            } else if c.is_ascii_digit() {
336                result.push(c);
337                last_digit_index = result.len();
338                _ = next(parser);
339            } else {
340                if result.len() != last_digit_index || c == b'-' || c == b'+' {
341                    panic!(
342                        r#"Number format is wrong.{}"#,
343                        get_current_status(parser)
344                    );
345                }
346                value_type = match d {
347                    0 => ValueType::Int,
348                    _ => ValueType::Float,
349                };
350                break;
351            }
352        }
353    } else {
354        let expected_word;
355        result.push(c);
356
357        // to support_capital_word, uncomment below line
358        // if c <= 90 { c += 32 }
359
360        if c == NULL[0] {
361            expected_word = NULL;
362            value_type = ValueType::Null;
363        } else if c == TRUE[0] {
364            expected_word = TRUE;
365            value_type = ValueType::Bool;
366        } else if c == FALSE[0] {
367            expected_word = FALSE;
368            value_type = ValueType::Bool;
369        } else {
370            panic!(
371                r#"Expecting "null | true | false" but found `{}`. {}"#,
372                c,
373                get_current_status(parser)
374            );
375        }
376        let l = expected_word.len();
377        d = 0;
378        loop {
379            d += 1;
380            if d >= l {
381                break;
382            }
383            c = next(parser);
384            result.push(c);
385
386            // to support_capital_word, uncomment below line
387            // if c <= 90 { c += 32 }
388
389            if c != expected_word[d] {
390                panic!(
391                    r#"Expecting "null, true, false" but found "{}". error info => {:?}"#,
392                    to_string(result),
393                    get_current_status(parser)
394                );
395            }
396        }
397    }
398    if parser.next_byte.is_ascii_whitespace() {
399        next_no_white_space(parser);
400    }
401    (value_type, to_string(result))
402}
403//endregion
404//region logic
405
406//region logic tools area
407pub struct StackItem {
408    next_executor: fn(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem,
409    pub key: Rc<String>,
410    pub level: f32,
411    pub nth: usize,
412    pub symbol: char,
413}
414
415#[derive(Debug, PartialEq)]
416pub enum TextItem {
417    Key(Item),
418    Value(Item),
419    None(u8),
420}
421
422/// pop then execute top
423fn pop_stack(parser: &mut Parser, top_index: usize) {
424    parser.stack.remove(top_index);
425    let i = top_index - 1;
426    (parser.stack[i].next_executor)(parser, i, NIL);
427}
428
429/// panic with current status
430fn panic(parser: &mut Parser, current_byte: u8) -> TextItem {
431    panic!(
432        r#"Unexpected char `{}`. {}"#,
433        current_byte as char,
434        get_current_status(parser)
435    );
436}
437
438/// json has tree structure. this function returns that path to the current position with some details
439pub fn get_path(parser: &mut Parser) -> Vec<PathItem> {
440    let l = parser.stack.len();
441    let mut path = Vec::with_capacity(l);
442    path.push(PathItem::Start);
443    for i in 0..l {
444        if parser.stack[i].symbol == '{' {
445            path.push(PathItem::Object(
446                parser.stack[i].key.clone(),
447                parser.stack[i].nth,
448            ))
449        } else if parser.stack[i].symbol == '[' {
450            path.push(PathItem::Array(
451                parser.stack[i].key.clone(),
452                parser.stack[i].nth,
453            ))
454        }
455    }
456    path
457}
458
459fn new_open_brace_stack_item(last_level: f32) -> StackItem {
460    StackItem {
461        next_executor: open_brace_start_state,
462        key: Rc::new(String::from("")),
463        level: (last_level + 1_f32).floor(),
464        nth: 0,
465        symbol: '{',
466    }
467}
468
469fn new_open_square_stack_item(key: Rc<String>, last_level: f32) -> StackItem {
470    StackItem {
471        next_executor: open_square_start_state,
472        key,
473        level: (last_level + 1_f32).floor(),
474        nth: 0,
475        symbol: '[',
476    }
477}
478
479fn new_colon_stack_item(key: Rc<String>, last_level: f32) -> StackItem {
480    StackItem {
481        next_executor: colon_start_state,
482        key,
483        level: last_level + 0.5,
484        nth: 0,
485        symbol: ':',
486    }
487}
488//endregion
489
490//region stack top is colon
491fn colon_start_state(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
492    let top = &mut parser.stack[top_index];
493    match current_byte {
494        b'"' => {
495            parser.stack.pop();
496            TextItem::Value(extract_string(parser))
497        }
498        b'{' => {
499            top.next_executor = colon_after_return_state;
500            let level = top.level;
501            parser.stack.push(new_open_brace_stack_item(level));
502            TextItem::None(current_byte)
503        }
504        b'[' => {
505            let key = top.key.clone();
506            top.next_executor = colon_after_return_state;
507            let level = top.level;
508            parser.stack.push(new_open_square_stack_item(key, level));
509            TextItem::None(current_byte)
510        }
511        b'}' | b']' | b',' | b':' => panic(parser, current_byte),
512        _ => {
513            parser.stack.pop();
514            TextItem::Value(extract_word(parser, current_byte))
515        }
516    }
517}
518
519fn colon_after_return_state(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
520    parser.stack.remove(top_index);
521    TextItem::None(current_byte)
522}
523//endregion
524
525//region stack top is open brace
526fn open_brace_start_state(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
527    match current_byte {
528        b'"' => {
529            let txt = extract_string(parser);
530            let top = &mut parser.stack[top_index];
531            top.next_executor = open_brace_after_key_state;
532            top.key = Rc::new(txt.1.clone());
533            TextItem::Key(txt)
534        }
535        b'}' => {
536            pop_stack(parser, top_index);
537            TextItem::None(current_byte)
538        }
539        _ => panic(parser, current_byte),
540    }
541}
542
543fn open_brace_after_key_state(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
544    let top = &mut parser.stack[top_index];
545    match current_byte {
546        b':' => {
547            let key = top.key.clone();
548            top.next_executor = open_brace_after_colon_state;
549            let level = top.level;
550            parser.stack.push(new_colon_stack_item(key, level));
551            TextItem::None(current_byte)
552        }
553        _ => panic(parser, current_byte),
554    }
555}
556
557fn open_brace_after_colon_state(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
558    let top = &mut parser.stack[top_index];
559    match current_byte {
560        b'}' => {
561            pop_stack(parser, top_index);
562            TextItem::None(current_byte)
563        }
564        b',' => {
565            top.next_executor = open_brace_start_state;
566            top.nth += 1;
567            TextItem::None(current_byte)
568        }
569        _ => panic(parser, current_byte),
570    }
571}
572//endregion
573
574//region stack top is open square
575fn open_square_start_state(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
576    let top = &mut parser.stack[top_index];
577    match current_byte {
578        b'"' => {
579            top.next_executor = open_square_after_single_value_state;
580            TextItem::Value(extract_string(parser))
581        }
582        b'{' => {
583            top.next_executor = open_square_after_return;
584            let level = top.level;
585            parser.stack.push(new_open_brace_stack_item(level));
586            TextItem::None(current_byte)
587        }
588        b'[' => {
589            let key = top.key.clone();
590            top.next_executor = open_square_after_return;
591            let level = top.level;
592            parser.stack.push(new_open_square_stack_item(key, level));
593            TextItem::None(current_byte)
594        }
595        b']' => {
596            pop_stack(parser, top_index);
597            TextItem::None(current_byte)
598        }
599        b',' | b':' | b'}' => panic(parser, current_byte),
600        _ => {
601            top.next_executor = open_square_after_single_value_state;
602            TextItem::Value(extract_word(parser, current_byte))
603        }
604    }
605}
606
607fn open_square_after_single_value_state(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
608    let top = &mut parser.stack[top_index];
609    match current_byte {
610        b']' => {
611            pop_stack(parser, top_index);
612            TextItem::None(current_byte)
613        }
614        b',' => {
615            top.next_executor = open_square_start_state;
616            top.nth += 1;
617            TextItem::None(current_byte)
618        }
619        _ => panic(parser, current_byte),
620    }
621}
622
623fn open_square_after_return(parser: &mut Parser, top_index: usize, current_byte: u8) -> TextItem {
624    let top = &mut parser.stack[top_index];
625    top.next_executor = open_square_after_single_value_state;
626    TextItem::None(current_byte)
627}
628//endregion
629//endregion
630
631//region high-level extractors
632fn extract_current_item(parser: &mut Parser) -> Item {
633    match walk_forward(parser) {
634        TextItem::Value(t) => t,
635        TextItem::Key(t) => t,
636        _ => panic!("Expected a value or key.{}", get_current_status(parser)),
637    }
638}
639
640// to be run when top is :
641pub fn extract_current_value(parser: &mut Parser, top_index: usize) -> Content {
642    return match parser.next_byte {
643        b'[' => {
644            walk_forward(parser);
645            extract_current_array(parser, top_index + 1)
646        }
647        b'{' => {
648            walk_forward(parser);
649            extract_current_object(parser, top_index + 1)
650        }
651        _ => match walk_forward(parser) {
652            TextItem::Value(t) => Content::Simple(t),
653            _ => {
654                panic!("Expecting a value.{}", get_current_status(parser))
655            }
656        },
657    };
658}
659
660// to be run when top is [
661fn extract_current_array(parser: &mut Parser, top_index: usize) -> Content {
662    let mut a: Vec<Content> = Vec::new();
663    loop {
664        match parser.next_byte {
665            b',' => {
666                walk_forward(parser);
667            }
668            b']' => {
669                walk_forward(parser);
670                break;
671            }
672            _ => {
673                a.push(extract_current_value(parser, top_index));
674            }
675        }
676    }
677    Content::Array(a)
678}
679
680// to be run when top is { and cursor is before a key
681fn extract_current_object(parser: &mut Parser, top_index: usize) -> Content {
682    let mut a: BTreeMap<String, Content> = BTreeMap::new();
683    let mut key;
684    let mut val;
685    loop {
686        key = match parser.next_byte {
687            b'}' => {
688                walk_forward(parser);
689                break;
690            }
691            _ => extract_current_item(parser),
692        }
693            .1;
694        walk_forward(parser);
695        val = extract_current_value(parser, top_index + 1);
696        a.insert(key, val);
697        match parser.next_byte {
698            b',' => {
699                walk_forward(parser);
700                continue;
701            }
702            b'}' => {
703                walk_forward(parser);
704                break;
705            }
706            _ => panic!("Unexpected char.{}", get_current_status(parser)),
707        }
708    }
709    Content::Object(a)
710}
711//endregion
712
713#[cfg(test)]
714mod parser_tests {
715    use std::panic::*;
716
717    use regex::Regex;
718
719    use crate::NIL;
720    use crate::parser_core::*;
721    use crate::readers::StringReader;
722
723    const CORRECT_JSON: &str = r#" {"key1":null,"key2":true,"key3":false,"key4":-111,"key5":+111.111,"key6":"str1 \":{}[],","key7":{  "key71" : null ,  "key72" : true ,  "key73" : false ,  "key74" : 222 ,  "key75" : 222.222 ,  "key76" : "str2 \":{}[]," ,  "key78" : [    null ,    true ,    false ,    -333 ,    +333.333 ,    "str3 \":{}[]," ,    {  } ,    [  ]  ] ,  "key79" : {} ,  "key710": [  ] } , "key8" : [  null ,  true ,  false ,  444 ,  444.444 ,  "str4 \":{}[]," ,  {    "key81" : null ,    "key82" : true ,    "key83" : false ,    "key84" : 555 ,
724      "key85" : 555.555 ,
725      "key86" : "str5 \":{}[]," ,    "key89" : {} ,    "key810" : [ ]  } ,  { } ,  [ ]  ] , "key9" : { } , "key10" : [ ]
726} "#;
727
728    #[ctor::ctor]
729    fn initialize() {
730        set_hook(Box::new(|_info| {
731            // println!("{}",info)
732        }));
733    }
734
735    fn execute_test(txt: &'static str, keys: &[&str], values: &[&str], chars: &[char]) {
736        let mut keys_index = 0;
737        let mut values_index = 0;
738        let mut chars_index = 0;
739        let result = catch_unwind(move || {
740            let mut parser = Parser::new(StringReader::new(txt.into()), 50);
741            while parser.next_byte != NIL {
742                let r = walk_forward(&mut parser);
743                match r {
744                    TextItem::Key(k) => {
745                        if k.1.ne(keys[keys_index]) {
746                            // println!(">>>>> {} != {}", keys[keys_index], k.1);
747                            panic!("expecting key: {}", k.1)
748                        }
749                        keys_index += 1;
750                    }
751                    TextItem::Value(v) => {
752                        if v.1.ne(values[values_index]) {
753                            // println!(">>>>> {} != {}", values[values_index], v.1);
754                            panic!("expecting value: {}", v.1)
755                        }
756                        values_index += 1;
757                    }
758                    TextItem::None(_) => {
759                        if chars_index >= chars.len() {
760                            // println!(">>>>> {} >= {}", chars_index, chars.len());
761                            panic!("expecting no more")
762                        }
763                        chars_index += 1;
764                    }
765                }
766            }
767        });
768        assert_eq!(result.is_ok(), true);
769    }
770
771    fn execute_for_panic(txt: &'static str) -> String {
772        let payload = catch_unwind(|| {
773            let mut parser = Parser::new(StringReader::new(txt.into()), 50);
774            while parser.next_byte != NIL {
775                walk_forward(&mut parser);
776            }
777        })
778            .unwrap_err();
779        String::from(panic_message::panic_message(&payload))
780    }
781
782    fn does_error_msg_ends_with(error_msg: &str, expected_ending: &str) -> Result<bool, ()> {
783        let raw_er;
784        let re = Regex::new(" nth: \\d+.+?\\.\\.\\.").unwrap();
785        match re.find(error_msg) {
786            None => {
787                raw_er = error_msg.to_owned();
788            }
789            Some(m) => {
790                let mut temp = &error_msg[m.start()..m.end()];
791                temp = &temp[temp.find(",").unwrap() + 1..];
792                let color_regex = Regex::new(r#"\x1b\[\d+m"#).unwrap();
793                raw_er = color_regex.replace_all(temp, "").trim().to_string();
794            }
795        }
796        let expected_len = expected_ending.len();
797        let end = if raw_er.ends_with("...") { raw_er.len() - 3 } else { raw_er.len() };
798        let start = if end > expected_len { end - expected_len } else { 0 };
799        Ok(expected_ending.eq(&raw_er[start..end]))
800    }
801
802    #[test]
803    fn correct_input_starting_with_brace() {
804        let keys = [
805            "key1", "key2", "key3", "key4", "key5", "key6", "key7", "key71", "key72", "key73",
806            "key74", "key75", "key76", "key78", "key79", "key710", "key8", "key81", "key82",
807            "key83", "key84", "key85", "key86", "key89", "key810", "key9", "key10",
808        ];
809        let values = [
810            "null",
811            "true",
812            "false",
813            "-111",
814            "+111.111",
815            "str1 \":{}[],",
816            "null",
817            "true",
818            "false",
819            "222",
820            "222.222",
821            "str2 \":{}[],",
822            "null",
823            "true",
824            "false",
825            "-333",
826            "+333.333",
827            "str3 \":{}[],",
828            "null",
829            "true",
830            "false",
831            "444",
832            "444.444",
833            "str4 \":{}[],",
834            "null",
835            "true",
836            "false",
837            "555",
838            "555.555",
839            "str5 \":{}[],",
840        ];
841        let chars = [
842            '{', ':', ',', ':', ',', ':', ',', ':', ',', ':', ',', ':', ',', ':', '{', ':', ',',
843            ':', ',', ':', ',', ':', ',', ':', ',', ':', ',', ':', '[', ',', ',', ',', ',', ',',
844            ',', '{', '}', ',', '[', ']', ']', ',', ':', '{', '}', ',', ':', '[', ']', '}', ',',
845            ':', '[', ',', ',', ',', ',', ',', ',', '{', ':', ',', ':', ',', ':', ',', ':', ',',
846            ':', ',', ':', ',', ':', '{', '}', ',', ':', '[', ']', '}', ',', '{', '}', ',', '[',
847            ']', ']', ',', ':', '{', '}', ',', ':', '[', ']', '}',
848        ];
849        execute_test(CORRECT_JSON, &keys, &values, &chars);
850    }
851
852    #[test]
853    fn correct_input_starting_with_square() {
854        let txt = r#"[ null , true , false , 444 , 444.444 , "str4 \":{}[]," , {"key81": null,"key82": true,"key83": false,"key84": 555,"key85": 555.555 , "key86": "str5 \":{}[],"} ]"#;
855        let keys = ["key81", "key82", "key83", "key84", "key85", "key86"];
856        let values = [
857            "null",
858            "true",
859            "false",
860            "444",
861            "444.444",
862            "str4 \":{}[],",
863            "null",
864            "true",
865            "false",
866            "555",
867            "555.555",
868            "str5 \":{}[],",
869        ];
870        let chars = [
871            '[', ',', ',', ',', ',', ',', ',', '{', ':', ',', ':', ',', ':', ',', ':', ',', ':',
872            ',', ':', '}', ']', '}',
873        ];
874        execute_test(txt, &keys, &values, &chars);
875    }
876
877    #[test]
878    fn incorrect_input_drop_key() {
879        let txt = r#"{:123}"#;
880        let result = execute_for_panic(txt);
881        assert!(does_error_msg_ends_with(&result, "{:1").is_ok_and(|b| b));
882    }
883
884    #[test]
885    fn incorrect_input_drop_colon() {
886        let txt = r#"{"key"123}"#;
887        let result = execute_for_panic(txt);
888        assert!(does_error_msg_ends_with(&result, r#"{"key"12"#).is_ok_and(|b| b));
889    }
890
891    #[test]
892    fn incorrect_input_drop_object_value() {
893        let txt = r#"{"key":,}"#;
894        let result = execute_for_panic(txt);
895        assert!(does_error_msg_ends_with(&result, r#"{"key":,}"#).is_ok_and(|b| b));
896    }
897
898    #[test]
899    fn incorrect_input_early_finish1() {
900        let txt = r#"{"key":}"#;
901        let result = execute_for_panic(txt);
902        assert_eq!(result, "Unexpected end of stream");
903    }
904
905    #[test]
906    fn incorrect_input_early_finish2() {
907        let txt = r#"{"key1":123,"key2":[}"#;
908        let result = execute_for_panic(txt);
909        assert_eq!(result, "Unexpected end of stream");
910    }
911
912    #[test]
913    fn incorrect_input_early_finish3() {
914        let txt = r#"{"key1":123,"key2":{}"#;
915        let result = execute_for_panic(txt);
916        assert_eq!(result, "Unexpected end of stream");
917    }
918
919    #[test]
920    fn incorrect_extra_input_start_with_brace() {
921        let txt = r#"{"key1":123,"key2":null},"#;
922        let result = execute_for_panic(txt);
923        assert!(does_error_msg_ends_with(&result, r#"stack is empty"#).is_ok_and(|b| b));
924    }
925
926    #[test]
927    fn incorrect_extra_input_start_with_square() {
928        let txt = r#"[123,null],"#;
929        let result = execute_for_panic(txt);
930        assert!(does_error_msg_ends_with(&result, r#"stack is empty"#).is_ok_and(|b| b));
931    }
932
933    #[test]
934    fn correct_input_start_with_single_value() {
935        let txt = r#""val123""#;
936        let mut parser = Parser::new(StringReader::new(txt.into()), 50);
937        let result = walk_forward(&mut parser);
938        match result {
939            TextItem::Value(v) => {
940                assert_eq!(v.1, "val123")
941            }
942            _ => {
943                assert_eq!(1, 2)
944            }
945        }
946    }
947
948    #[test]
949    fn walk_till_child_node() {
950        let mut parser = Parser::new(StringReader::new(CORRECT_JSON.into()), 50);
951        let result = seek_by_level_offset(&mut parser, 2.0);
952        assert!(result);
953        let item = walk_forward(&mut parser);
954        assert_eq!(item, TextItem::Key((ValueType::Str, String::from("key71"))));
955    }
956
957    #[test]
958    fn walk_till_parent_node() {
959        let mut parser = Parser::new(StringReader::new(CORRECT_JSON.into()), 50);
960        seek_by_level_offset(&mut parser, 2.0);
961        seek_by_level_offset(&mut parser, -1.0);
962        let item = walk_forward(&mut parser);
963        assert_eq!(item, TextItem::None(b','));
964        let item = walk_forward(&mut parser);
965        assert_eq!(item, TextItem::Key((ValueType::Str, String::from("key8"))))
966    }
967
968    #[test]
969    fn catch_sibling_nodes_of_object() {
970        let items = ["key71", "key72", "key73", "key74", "key75", "key76", "key78", "key79", "key710"];
971        let mut index = 0;
972        let mut parser = Parser::new(StringReader::new(CORRECT_JSON.into()), 50);
973        let mut result = seek_by_level_offset(&mut parser, 2.0);
974        while result {
975            let item = walk_forward(&mut parser);
976            match item {
977                TextItem::Key(m) => {
978                    assert_eq!(m.1, items[index]);
979                    index += 1;
980                }
981                TextItem::None(b',') => {
982                    continue;
983                }
984                _ => {
985                    assert!(false, "it is not supposed to get any item other than key")
986                }
987            }
988            result = seek_by_level_offset(&mut parser, 0.0);
989        }
990    }
991
992    #[test]
993    fn catch_sibling_nodes_of_array() {
994        let items = ["null", "true", "false", "444", "444.444", "str4 \":{}[],"];
995        let mut index = 0;
996
997        let mut parser = Parser::new(StringReader::new(CORRECT_JSON.into()), 50);
998
999        loop {
1000            let item = walk_forward(&mut parser);
1001            match item {
1002                TextItem::Key(k) => { if k.1.eq("key8") { break; } }
1003                _ => {}
1004            }
1005        }
1006
1007        let mut result = seek_by_level_offset(&mut parser, 1.0);
1008        let mut diff = 0.0;
1009        while result {
1010            let item = walk_forward(&mut parser);
1011            match item {
1012                TextItem::Value(m) => {
1013                    assert_eq!(m.1, items[index]);
1014                    index += 1;
1015                    diff = 0.0;
1016                }
1017                TextItem::None(b',') => {
1018                    diff = 0.0;
1019                }
1020                TextItem::None(b'{') | TextItem::None(b'[') => {
1021                    diff = -1.0;
1022                }
1023                _ => {
1024                    assert!(true, "It is not supposed to face any item other than value, comma, open brace or open square")
1025                }
1026            }
1027            result = seek_by_level_offset(&mut parser, diff);
1028        }
1029    }
1030}