jzon/
parser.rs

1// HERE BE DRAGONS!
2// ================
3//
4// Making a fast parser is hard. This is a _not so naive_ implementation of
5// recursive descent that does almost nothing. _There is no backtracking_, the
6// whole parsing is 100% predictive, even though it's not BNF, and will have
7// linear performance based on the length of the source!
8//
9// There is a lot of macros here! Like, woah! This is mostly due to the fact
10// that Rust isn't very cool about optimizing inlined functions that return
11// a `Result` type. Since different functions will have different `Result`
12// signatures, the `try!` macro will always have to repackage our results.
13// With macros those issues don't exist, the macro will return an unpackaged
14// result - whatever it is - and if we ever stumble upon the error, we can
15// return an `Err` without worrying about the exact signature of `Result`.
16//
17// This makes for some ugly code, but it is faster. Hopefully in the future
18// with MIR support the compiler will get smarter about this.
19
20use std::{str, slice};
21use std::char::decode_utf16;
22use std::convert::TryFrom;
23use crate::object::Object;
24use crate::number::Number;
25use crate::{JsonValue, Error, Result};
26
27// This is not actual max precision, but a threshold at which number parsing
28// kicks into checked math.
29const MAX_PRECISION: u64 = 576460752303423500;
30
31
32// How many nested Objects/Arrays are allowed to be parsed
33const DEPTH_LIMIT: usize = 512;
34
35
36// The `Parser` struct keeps track of indexing over our buffer. All niceness
37// has been abandoned in favor of raw pointer magic. Does that make you feel
38// dirty? _Good._
39struct Parser<'a> {
40    // Helper buffer for parsing strings that can't be just memcopied from
41    // the original source (escaped characters)
42    buffer: Vec<u8>,
43
44    // String slice to parse
45    source: &'a str,
46
47    // Byte pointer to the slice above
48    byte_ptr: *const u8,
49
50    // Current index
51    index: usize,
52
53    // Length of the source
54    length: usize,
55}
56
57
58// Read a byte from the source.
59// Will return an error if there are no more bytes.
60macro_rules! expect_byte {
61    ($parser:ident) => ({
62        if $parser.is_eof() {
63            return Err(Error::UnexpectedEndOfJson);
64        }
65
66        let ch = $parser.read_byte();
67        $parser.bump();
68        ch
69    })
70}
71
72
73// Expect a sequence of specific bytes in specific order, error otherwise.
74// This is useful for reading the 3 JSON identifiers:
75//
76// - "t" has to be followed by "rue"
77// - "f" has to be followed by "alse"
78// - "n" has to be followed by "ull"
79//
80// Anything else is an error.
81macro_rules! expect_sequence {
82    ($parser:ident, $( $ch:pat ),*) => {
83        $(
84            match expect_byte!($parser) {
85                $ch => {},
86                _   => return $parser.unexpected_character(),
87            }
88        )*
89    }
90}
91
92
93// A drop in macro for when we expect to read a byte, but we don't care
94// about any whitespace characters that might occur before it.
95macro_rules! expect_byte_ignore_whitespace {
96    ($parser:ident) => ({
97        let mut ch = expect_byte!($parser);
98
99        // Don't go straight for the loop, assume we are in the clear first.
100        match ch {
101            // whitespace
102            9 ..= 13 | 32 => {
103                loop {
104                    match expect_byte!($parser) {
105                        9 ..= 13 | 32 => {},
106                        next          => {
107                            ch = next;
108                            break;
109                        }
110                    }
111                }
112            },
113            _ => {}
114        }
115
116        ch
117    })
118}
119
120// Expect to find EOF or just whitespaces leading to EOF after a JSON value
121macro_rules! expect_eof {
122    ($parser:ident) => ({
123        while !$parser.is_eof() {
124            match $parser.read_byte() {
125                9 ..= 13 | 32 => $parser.bump(),
126                _             => {
127                    $parser.bump();
128                    return $parser.unexpected_character();
129                }
130            }
131        }
132    })
133}
134
135// Expect a particular byte to be next. Also available with a variant
136// creates a `match` expression just to ease some pain.
137macro_rules! expect {
138    ($parser:ident, $byte:expr) => ({
139        let ch = expect_byte_ignore_whitespace!($parser);
140
141        if ch != $byte {
142            return $parser.unexpected_character()
143        }
144    });
145
146    {$parser:ident $(, $byte:pat => $then:expr )*} => ({
147        let ch = expect_byte_ignore_whitespace!($parser);
148
149        match ch {
150            $(
151                $byte => $then,
152            )*
153            _ => return $parser.unexpected_character()
154        }
155
156    })
157}
158
159
160// Look up table that marks which characters are allowed in their raw
161// form in a string.
162const QU: bool = false;  // double quote       0x22
163const BS: bool = false;  // backslash          0x5C
164const CT: bool = false;  // control character  0x00 ..= 0x1F
165const __: bool = true;
166
167static ALLOWED: [bool; 256] = [
168// 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
169  CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 0
170  CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 1
171  __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2
172  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3
173  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4
174  __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5
175  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6
176  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7
177  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8
178  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9
179  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A
180  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B
181  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C
182  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D
183  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E
184  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
185];
186
187
188// Expect a string. This is called after encountering, and consuming, a
189// double quote character. This macro has a happy path variant where it
190// does almost nothing as long as all characters are allowed (as described
191// in the look up table above). If it encounters a closing quote without
192// any escapes, it will use a slice straight from the source, avoiding
193// unnecessary buffering.
194macro_rules! expect_string {
195    ($parser:ident) => ({
196        let result: &str;
197        let start = $parser.index;
198
199        loop {
200            let ch = expect_byte!($parser);
201            if ALLOWED[ch as usize] {
202                continue;
203            }
204            if ch == b'"' {
205                unsafe {
206                    let ptr = $parser.byte_ptr.offset(start as isize);
207                    let len = $parser.index - 1 - start;
208                    result = str::from_utf8_unchecked(slice::from_raw_parts(ptr, len));
209                }
210                break;
211            }
212            if ch == b'\\' {
213                result = $parser.read_complex_string(start)?;
214                break;
215            }
216
217            return $parser.unexpected_character();
218        }
219
220        result
221    })
222}
223
224
225// Expect a number. Of some kind.
226macro_rules! expect_number {
227    ($parser:ident, $first:ident) => ({
228        let mut num = ($first - b'0') as u64;
229
230        let result: Number;
231
232        // Cap on how many iterations we do while reading to u64
233        // in order to avoid an overflow.
234        loop {
235            if num >= MAX_PRECISION {
236                result = $parser.read_big_number(num)?;
237                break;
238            }
239
240            if $parser.is_eof() {
241                result = num.into();
242                break;
243            }
244
245            let ch = $parser.read_byte();
246
247            match ch {
248                b'0' ..= b'9' => {
249                    $parser.bump();
250                    num = num * 10 + (ch - b'0') as u64;
251                },
252                _             => {
253                    let mut e = 0;
254                    result = allow_number_extensions!($parser, num, e, ch);
255                    break;
256                }
257            }
258        }
259
260        result
261    })
262}
263
264
265// Invoked after parsing an integer, this will account for fractions and/or
266// `e` notation.
267macro_rules! allow_number_extensions {
268    ($parser:ident, $num:ident, $e:ident, $ch:ident) => ({
269        match $ch {
270            b'.'        => {
271                $parser.bump();
272                expect_fraction!($parser, $num, $e)
273            },
274            b'e' | b'E' => {
275                $parser.bump();
276                $parser.expect_exponent($num, $e)?
277            },
278            _  => $num.into()
279        }
280    });
281
282    // Alternative variant that defaults everything to 0. This is actually
283    // quite handy as the only number that can begin with zero, has to have
284    // a zero mantissa. Leading zeroes are illegal in JSON!
285    ($parser:ident) => ({
286        if $parser.is_eof() {
287            0.into()
288        } else {
289            let mut num = 0;
290            let mut e = 0;
291            let ch = $parser.read_byte();
292            allow_number_extensions!($parser, num, e, ch)
293        }
294    })
295}
296
297
298// If a dot `b"."` byte has been read, start reading the decimal fraction
299// of the number.
300macro_rules! expect_fraction {
301    ($parser:ident, $num:ident, $e:ident) => ({
302        let result: Number;
303
304        let ch = expect_byte!($parser);
305
306        match ch {
307            b'0' ..= b'9' => {
308                if $num < MAX_PRECISION {
309                    $num = $num * 10 + (ch - b'0') as u64;
310                    $e -= 1;
311                } else {
312                    match $num.checked_mul(10).and_then(|num| {
313                        num.checked_add((ch - b'0') as u64)
314                    }) {
315                        Some(result) => {
316                            $num = result;
317                            $e -= 1;
318                        },
319                        None => {}
320                    }
321                }
322            },
323            _ => return $parser.unexpected_character()
324        }
325
326        loop {
327            if $parser.is_eof() {
328                result = unsafe { Number::from_parts_unchecked(true, $num, $e) };
329                break;
330            }
331            let ch = $parser.read_byte();
332
333            match ch {
334                b'0' ..= b'9' => {
335                    $parser.bump();
336                    if $num < MAX_PRECISION {
337                        $num = $num * 10 + (ch - b'0') as u64;
338                        $e -= 1;
339                    } else {
340                        match $num.checked_mul(10).and_then(|num| {
341                            num.checked_add((ch - b'0') as u64)
342                        }) {
343                            Some(result) => {
344                                $num = result;
345                                $e -= 1;
346                            },
347                            None => {}
348                        }
349                    }
350                },
351                b'e' | b'E' => {
352                    $parser.bump();
353                    result = $parser.expect_exponent($num, $e)?;
354                    break;
355                }
356                _ => {
357                    result = unsafe { Number::from_parts_unchecked(true, $num, $e) };
358                    break;
359                }
360            }
361        }
362
363        result
364    })
365}
366
367impl<'a> Parser<'a> {
368    pub fn new(source: &'a str) -> Self {
369        Parser {
370            buffer: Vec::with_capacity(30),
371            source: source,
372            byte_ptr: source.as_ptr(),
373            index: 0,
374            length: source.len(),
375        }
376    }
377
378    // Check if we are at the end of the source.
379    #[inline(always)]
380    fn is_eof(&mut self) -> bool {
381        self.index == self.length
382    }
383
384    // Read a byte from the source. Note that this does not increment
385    // the index. In few cases (all of them related to number parsing)
386    // we want to peek at the byte before doing anything. This will,
387    // very very rarely, lead to a situation where the same byte is read
388    // twice, but since this operation is using a raw pointer, the cost
389    // is virtually irrelevant.
390    #[inline(always)]
391    fn read_byte(&mut self) -> u8 {
392        debug_assert!(self.index < self.length, "Reading out of bounds");
393
394        unsafe { *self.byte_ptr.offset(self.index as isize) }
395    }
396
397    // Manually increment the index. Calling `read_byte` and then `bump`
398    // is equivalent to consuming a byte on an iterator.
399    #[inline(always)]
400    fn bump(&mut self) {
401        self.index = self.index.wrapping_add(1);
402    }
403
404    // So we got an unexpected character, now what? Well, figure out where
405    // it is, and throw an error!
406    fn unexpected_character<T: Sized>(&mut self) -> Result<T> {
407        let at = self.index - 1;
408
409        let ch = self.source[at..]
410                     .chars()
411                     .next()
412                     .expect("Must have a character");
413
414        let (lineno, col) = self.source[..at]
415                                .lines()
416                                .enumerate()
417                                .last()
418                                .unwrap_or((0, ""));
419
420        let colno = col.chars().count();
421
422        Err(Error::UnexpectedCharacter {
423            ch: ch,
424            line: lineno + 1,
425            column: colno + 1,
426        })
427    }
428
429    // Boring
430    fn read_hexdec_digit(&mut self) -> Result<u16> {
431        let ch = expect_byte!(self);
432        Ok(match ch {
433            b'0' ..= b'9' => (ch - b'0'),
434            b'a' ..= b'f' => (ch + 10 - b'a'),
435            b'A' ..= b'F' => (ch + 10 - b'A'),
436            _             => return self.unexpected_character(),
437        } as u16)
438    }
439
440    // Boring
441    fn read_hexdec_codepoint(&mut self) -> Result<u16> {
442        Ok(
443            self.read_hexdec_digit()? << 12 |
444            self.read_hexdec_digit()? << 8  |
445            self.read_hexdec_digit()? << 4  |
446            self.read_hexdec_digit()?
447        )
448    }
449
450    // Oh look, some action. This method reads an escaped unicode
451    // sequence such as `\uDEAD` from the string. Except `DEAD` is
452    // not a valid codepoint, so it also needs to handle errors...
453    fn read_codepoint(&mut self) -> Result<()> {
454        let mut buf = [0; 4];
455        let codepoint = self.read_hexdec_codepoint()?;
456
457        let unicode = match char::try_from(codepoint as u32) {
458            Ok(code) => code,
459            // Handle surrogate pairs
460            Err(_) => {
461                expect_sequence!(self, b'\\', b'u');
462
463                match decode_utf16(
464                    [codepoint, self.read_hexdec_codepoint()?].iter().copied()
465                ).next() {
466                    Some(Ok(code)) => code,
467                    _ => return Err(Error::FailedUtf8Parsing),
468                }
469            }
470        };
471
472        self.buffer.extend_from_slice(unicode.encode_utf8(&mut buf).as_bytes());
473
474        Ok(())
475    }
476
477    // What's so complex about strings you may ask? Not that much really.
478    // This method is called if the `expect_string!` macro encounters an
479    // escape. The added complexity is that it will have to use an internal
480    // buffer to read all the escaped characters into, before finally
481    // producing a usable slice. What it means it that parsing "foo\bar"
482    // is whole lot slower than parsing "foobar", as the former suffers from
483    // having to be read from source to a buffer and then from a buffer to
484    // our target string. Nothing to be done about this, really.
485    fn read_complex_string(&mut self, start: usize) -> Result<&'_ str> {
486        // Since string slices are returned by this function that are created via pointers into `self.buffer`
487        // we shouldn't be clearing or modifying the buffer in consecutive calls to this function. Instead
488        // we continuously append bytes to `self.buffer` and keep track of the starting offset of the buffer on each
489        // call to this function. Later when creating string slices that point to the contents of this buffer
490        // we use this starting offset to make sure that newly created slices point only to the bytes that were
491        // appended in the most recent call to this function.
492        //
493        // Failing to do this can result in the StackBlock `key` values being modified in place later.
494        let len = self.buffer.len();
495        //self.buffer.clear();
496        let mut ch = b'\\';
497
498        // TODO: Use fastwrite here as well
499        self.buffer.extend_from_slice(&self.source.as_bytes()[start .. self.index - 1]);
500
501        loop {
502            if ALLOWED[ch as usize] {
503                self.buffer.push(ch);
504                ch = expect_byte!(self);
505                continue;
506            }
507            match ch {
508                b'"'  => break,
509                b'\\' => {
510                    let escaped = expect_byte!(self);
511                    let escaped = match escaped {
512                        b'u'  => {
513                            self.read_codepoint()?;
514                            ch = expect_byte!(self);
515                            continue;
516                        },
517                        b'"'  |
518                        b'\\' |
519                        b'/'  => escaped,
520                        b'b'  => 0x8,
521                        b'f'  => 0xC,
522                        b't'  => b'\t',
523                        b'r'  => b'\r',
524                        b'n'  => b'\n',
525                        _     => return self.unexpected_character()
526                    };
527                    self.buffer.push(escaped);
528                },
529                _ => return self.unexpected_character()
530            }
531            ch = expect_byte!(self);
532        }
533
534        // Since the original source is already valid UTF-8, and `\`
535        // cannot occur in front of a codepoint > 127, this is safe.
536        Ok(unsafe {
537            str::from_utf8_unchecked(
538                // Because the buffer is stored on the parser, returning it
539                // as a slice here freaks out the borrow checker. The compiler
540                // can't know that the buffer isn't used till the result
541                // of this function is long used and irrelevant. To avoid
542                // issues here, we construct a new slice from raw parts, which
543                // then has lifetime bound to the outer function scope instead
544                // of the parser itself.
545                slice::from_raw_parts(self.buffer[len .. ].as_ptr(), self.buffer.len() - len)
546            )
547        })
548    }
549
550    // Big numbers! If the `expect_number!` reaches a point where the decimal
551    // mantissa could have overflown the size of u64, it will switch to this
552    // control path instead. This method will pick up where the macro started,
553    // but instead of continuing to read into the mantissa, it will increment
554    // the exponent. Note that no digits are actually read here, as we already
555    // exceeded the precision range of f64 anyway.
556    fn read_big_number(&mut self, mut num: u64) -> Result<Number> {
557        let mut e = 0i16;
558        loop {
559            if self.is_eof() {
560                return Ok(unsafe { Number::from_parts_unchecked(true, num, e) });
561            }
562            let ch = self.read_byte();
563            match ch {
564                b'0' ..= b'9' => {
565                    self.bump();
566                    match num.checked_mul(10).and_then(|num| {
567                        num.checked_add((ch - b'0') as u64)
568                    }) {
569                        Some(result) => num = result,
570                        None         => e = e.checked_add(1).ok_or_else(|| Error::ExceededDepthLimit)?,
571                    }
572                },
573                b'.' => {
574                    self.bump();
575                    return Ok(expect_fraction!(self, num, e));
576                },
577                b'e' | b'E' => {
578                    self.bump();
579                    return self.expect_exponent(num, e);
580                }
581                _  => break
582            }
583        }
584
585        Ok(unsafe { Number::from_parts_unchecked(true, num, e) })
586    }
587
588    // Called in the rare case that a number with `e` notation has been
589    // encountered. This is pretty straight forward, I guess.
590    fn expect_exponent(&mut self, num: u64, big_e: i16) -> Result<Number> {
591        let mut ch = expect_byte!(self);
592        let sign = match ch {
593            b'-' => {
594                ch = expect_byte!(self);
595                -1
596            },
597            b'+' => {
598                ch = expect_byte!(self);
599                1
600            },
601            _    => 1
602        };
603
604        let mut e = match ch {
605            b'0' ..= b'9' => (ch - b'0') as i16,
606            _ => return self.unexpected_character(),
607        };
608
609        loop {
610            if self.is_eof() {
611                break;
612            }
613            let ch = self.read_byte();
614            match ch {
615                b'0' ..= b'9' => {
616                    self.bump();
617                    e = e.saturating_mul(10).saturating_add((ch - b'0') as i16);
618                },
619                _  => break
620            }
621        }
622
623        Ok(unsafe { Number::from_parts_unchecked(true, num, big_e.saturating_add(e * sign)) })
624    }
625
626    // Parse away!
627    fn parse(&mut self) -> Result<JsonValue> {
628        let mut stack = Vec::with_capacity(3);
629        let mut ch = expect_byte_ignore_whitespace!(self);
630
631        'parsing: loop {
632            let mut value = match ch {
633                b'[' => {
634                    ch = expect_byte_ignore_whitespace!(self);
635
636                    if ch != b']' {
637                        if stack.len() == DEPTH_LIMIT {
638                            return Err(Error::ExceededDepthLimit);
639                        }
640
641                        stack.push(StackBlock(JsonValue::Array(Vec::with_capacity(2)), 0));
642                        continue 'parsing;
643                    }
644
645                    JsonValue::Array(Vec::new())
646                },
647                b'{' => {
648                    ch = expect_byte_ignore_whitespace!(self);
649
650                    if ch != b'}' {
651                        if stack.len() == DEPTH_LIMIT {
652                            return Err(Error::ExceededDepthLimit);
653                        }
654
655                        let mut object = Object::with_capacity(3);
656
657                        if ch != b'"' {
658                            return self.unexpected_character()
659                        }
660
661                        let index = object.insert_index(expect_string!(self), JsonValue::Null);
662                        expect!(self, b':');
663
664                        stack.push(StackBlock(JsonValue::Object(object), index));
665
666                        ch = expect_byte_ignore_whitespace!(self);
667
668                        continue 'parsing;
669                    }
670
671                    JsonValue::Object(Object::new())
672                },
673                b'"' => expect_string!(self).into(),
674                b'0' => JsonValue::Number(allow_number_extensions!(self)),
675                b'1' ..= b'9' => {
676                    JsonValue::Number(expect_number!(self, ch))
677                },
678                b'-' => {
679                    let ch = expect_byte!(self);
680                    JsonValue::Number(- match ch {
681                        b'0' => allow_number_extensions!(self),
682                        b'1' ..= b'9' => expect_number!(self, ch),
683                        _    => return self.unexpected_character()
684                    })
685                }
686                b't' => {
687                    expect_sequence!(self, b'r', b'u', b'e');
688                    JsonValue::Boolean(true)
689                },
690                b'f' => {
691                    expect_sequence!(self, b'a', b'l', b's', b'e');
692                    JsonValue::Boolean(false)
693                },
694                b'n' => {
695                    expect_sequence!(self, b'u', b'l', b'l');
696                    JsonValue::Null
697                },
698                _    => return self.unexpected_character()
699            };
700
701            'popping: loop {
702                match stack.last_mut() {
703                    None => {
704                        expect_eof!(self);
705
706                        return Ok(value);
707                    },
708
709                    Some(&mut StackBlock(JsonValue::Array(ref mut array), _)) => {
710                        array.push(value);
711
712                        ch = expect_byte_ignore_whitespace!(self);
713
714                        match ch {
715                            b',' => {
716                                ch = expect_byte_ignore_whitespace!(self);
717
718                                continue 'parsing;
719                            },
720                            b']' => {},
721                            _    => return self.unexpected_character()
722                        }
723                    },
724
725                    Some(&mut StackBlock(JsonValue::Object(ref mut object), ref mut index )) => {
726                        object.override_at(*index, value);
727
728                        ch = expect_byte_ignore_whitespace!(self);
729
730                        match ch {
731                            b',' => {
732                                expect!(self, b'"');
733                                *index = object.insert_index(expect_string!(self), JsonValue::Null);
734                                expect!(self, b':');
735
736                                ch = expect_byte_ignore_whitespace!(self);
737
738                                continue 'parsing;
739                            },
740                            b'}' => {},
741                            _    => return self.unexpected_character()
742                        }
743                    },
744
745                    _ => unreachable!(),
746                }
747
748                value = match stack.pop() {
749                    Some(StackBlock(value, _)) => value,
750                    None                       => break 'popping
751                }
752            }
753        }
754    }
755}
756
757struct StackBlock(JsonValue, usize);
758
759// All that hard work, and in the end it's just a single function in the API.
760#[inline]
761pub fn parse(source: &str) -> Result<JsonValue> {
762    Parser::new(source).parse()
763}
764
765
766#[cfg(test)]
767mod tests {
768    use super::*;
769    use crate::stringify;
770    use crate::JsonValue;
771
772    use crate::object;
773    use crate::array;
774
775    use std::fs::File;
776    use std::io::prelude::*;
777
778    #[test]
779    fn it_should_parse_escaped_forward_slashes_with_quotes() {
780        // used to get around the fact that rust strings don't escape forward slashes
781        let mut file = File::open("tests/test_json_slashes_quotes").unwrap();
782        let mut contents = String::new();
783        file.read_to_string(&mut contents).unwrap();
784
785        let actual = parse(&contents).unwrap();
786        let serialized = stringify(actual.clone());
787
788        assert_eq!(serialized, contents);
789    }
790
791    #[test]
792    fn it_should_parse_escaped_quotes() {
793        let contents = String::from("{\"ab\":\"c\\\"d\\\"e\"}");
794
795        let actual = parse(&contents).unwrap();
796        let serialized = stringify(actual.clone());
797
798        assert_eq!(serialized, contents);
799    }
800
801    #[test]
802    fn it_should_parse_basic_json_values() {
803        let s = "{\"a\":1,\"b\":true,\"c\":false,\"d\":null,\"e\":2}";
804        let actual = parse(s).unwrap();
805        let mut expected = object! {
806            a: 1,
807            b: true,
808            c: false,
809            e: 2,
810        };
811        expected["d"] = JsonValue::Null;
812
813        assert_eq!(actual, expected);
814    }
815
816    #[test]
817    fn it_should_parse_json_arrays() {
818        let s = "{\"a\":1,\"b\":true,\"c\":false,\"d\":null,\"e\":2,\"f\":[1,2,3,false,true,[],{}]}";
819        let actual = parse(s).unwrap();
820        let mut expected = object! {
821            a: 1,
822            b: true,
823            c: false,
824            e: 2,
825        };
826        expected["d"] = JsonValue::Null;
827        expected["f"] = array![
828            1,2,3,
829            false,
830            true,
831            [],
832            {},
833        ];
834
835        assert_eq!(actual, expected);
836    }
837
838    #[test]
839    fn it_should_parse_json_nested_object() {
840        let s = "{\"a\":1,\"b\":{\"c\":2,\"d\":{\"e\":{\"f\":{\"g\":3,\"h\":[]}}},\"i\":4,\"j\":[],\"k\":{\"l\":5,\"m\":{}}}}";
841        let actual = parse(s).unwrap();
842        let expected = object! {
843            a: 1,
844            b: {
845                c: 2,
846                d: {
847                    e: {
848                        f: {
849                            g: 3,
850                            h: []
851                        }
852                    }
853                },
854                i: 4,
855                j: [],
856                k: {
857                    l: 5,
858                    m: {}
859                }
860            }
861        };
862
863        assert_eq!(actual, expected);
864    }
865
866    #[test]
867    fn it_should_parse_json_complex_object() {
868        let s = "{\"a\":1,\"b\":{\"c\":2,\"d\":{\"e\":{\"f\":{\"g\":3,\"h\":[{\"z\":1},{\"y\":2,\"x\":[{},{}]}]}}},\"i\":4,\"j\":[],\"k\":{\"l\":5,\"m\":{}}}}";
869        let actual = parse(s).unwrap();
870        let expected = object! {
871            a: 1,
872            b: {
873                c: 2,
874                d: {
875                    e: {
876                        f: {
877                            g: 3,
878                            h: [
879                                { z: 1 },
880                                { y: 2, x: [{}, {}]}
881                            ]
882                        }
883                    }
884                },
885                i: 4,
886                j: [],
887                k: {
888                    l: 5,
889                    m: {}
890                }
891            }
892        };
893
894        assert_eq!(actual, expected);
895    }
896
897}