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
11struct 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}
46pub 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 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}
139fn 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
151fn next_byte(parser: &mut Parser) -> u8 {
153 parser
154 .reader
155 .next()
156 .unwrap_or_else(|| on_none_input(parser))
157}
158
159fn 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
172fn next(parser: &mut Parser) -> u8 {
174 let c = parser.next_byte;
183 parser.next_byte = (parser.next_fn)(parser);
184 c
185}
186
187fn 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
199pub 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}
213fn to_string(v: Vec<u8>) -> String {
215 String::from_utf8(v).expect("This input is not utf8 formatted string")
216}
217
218pub 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
230pub 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
247pub fn get_current_level(parser: &Parser) -> f32 {
250 match parser.stack.last() {
251 None => { -1.0 }
252 Some(t) => { t.level }
253 }
254}
255
256pub 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 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 {
281 return parser.next_byte != b'}' && parser.next_byte != b']';
282 }
283 }
284 false
285}
286
287pub fn get_recent_piece(parser: &mut Parser) -> String {
289 parser.txt.to_string()
290}
291fn 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
314fn 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 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 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}
403pub 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
422fn 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
429fn 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
438pub 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}
488fn 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}
523fn 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}
572fn 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}
628fn 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
640pub 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
660fn 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
680fn 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#[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 }));
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 panic!("expecting key: {}", k.1)
748 }
749 keys_index += 1;
750 }
751 TextItem::Value(v) => {
752 if v.1.ne(values[values_index]) {
753 panic!("expecting value: {}", v.1)
755 }
756 values_index += 1;
757 }
758 TextItem::None(_) => {
759 if chars_index >= chars.len() {
760 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}