hipack/
parser.rs

1// Copyright 2015-2016 hipack-rs developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::io;
10use std::fmt;
11use std::error;
12use std::result;
13use std::collections::BTreeMap;
14use super::value::Value;
15use std::f64::{NAN, INFINITY};
16
17
18#[derive(Clone, PartialEq)]
19pub enum ErrorCode {
20    ExpectedDictKey,
21    ExpectedSeparator,
22    InvalidBoolValue,
23    InvalidNumberValue,
24    InvalidEscapeSequence,
25    InvalidUtf8Sequence,
26    UnexpectedEOF,
27    UnterminatedMessage,
28    UnterminatedString,
29    UnterminatedList,
30    UnterminatedDict,
31}
32
33
34impl fmt::Debug for ErrorCode {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        (match *self {
37            ErrorCode::ExpectedDictKey       => "Dictionary key expected",
38            ErrorCode::ExpectedSeparator     => "Separator expected",
39            ErrorCode::InvalidBoolValue      => "Invalid boolean value",
40            ErrorCode::InvalidNumberValue    => "Invalid numeric value",
41            ErrorCode::InvalidEscapeSequence => "Invalid escape sequence",
42            ErrorCode::InvalidUtf8Sequence   => "Invalid UTF-8 sequence",
43            ErrorCode::UnexpectedEOF         => "Unexpected end of file",
44            ErrorCode::UnterminatedMessage   => "Unterminated message",
45            ErrorCode::UnterminatedString    => "Unterminated string",
46            ErrorCode::UnterminatedList      => "Unterminated list",
47            ErrorCode::UnterminatedDict      => "Unterminated dictionary",
48        }).fmt(f)
49    }
50}
51
52
53#[derive(Debug)]
54pub enum Error {
55    SyntaxError(ErrorCode, usize, usize), // Error, line, column
56    IoError(io::Error),
57}
58
59
60impl error::Error for Error {
61    fn description(&self) -> &str {
62        match *self {
63            Error::SyntaxError(..) => "syntax error",
64            Error::IoError(ref error) => error::Error::description(error),
65        }
66    }
67
68    fn cause(&self) -> Option<&error::Error> {
69        match *self {
70            Error::IoError(ref error) => Some(error),
71            _ => None,
72        }
73    }
74}
75
76
77impl fmt::Display for Error {
78    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79        match *self {
80            Error::SyntaxError(ref code, line, column) =>
81                write!(f, "{:?} at line {} column {}", code, line, column),
82            Error::IoError(ref error) =>
83                fmt::Display::fmt(error, f),
84        }
85    }
86}
87
88
89impl From<io::Error> for Error {
90    fn from(error: io::Error) -> Error {
91        Error::IoError(error)
92    }
93}
94
95
96pub type Result<T> = result::Result<T, Error>;
97
98
99#[inline]
100fn is_whitespace_character(ch: u8) -> bool {
101    match ch { 0x09  // Horizontal tab.
102             | 0x0A  // New line.
103             | 0x0D  // Carriage return.
104             | 0x20  // Space.
105               => true,
106             _ => false,
107    }
108}
109
110
111#[inline]
112fn is_key_character(ch: u8) -> bool {
113    match ch {
114        b'[' | b']' | b'{' | b'}' | b':' | b',' => false, // Forbidden in keys by the spec
115        _ => !is_whitespace_character(ch),
116    }
117}
118
119
120#[inline]
121fn is_xdigit_character(ch: u8) -> bool {
122    match ch { b'0'...b'9'
123             | b'a'...b'f'
124             | b'A'...b'F'
125               => true,
126             _ => false,
127    }
128}
129
130
131#[inline]
132fn xdigit_to_int(ch: u8) -> u8 {
133    match ch {
134        b'0' => 0,
135        b'1' => 1,
136        b'2' => 2,
137        b'3' => 3,
138        b'4' => 4,
139        b'5' => 5,
140        b'6' => 6,
141        b'7' => 7,
142        b'8' => 8,
143        b'9' => 9,
144        b'a' | b'A' => 0xA,
145        b'b' | b'B' => 0xB,
146        b'c' | b'C' => 0xC,
147        b'd' | b'D' => 0xD,
148        b'e' | b'E' => 0xE,
149        b'f' | b'F' => 0xF,
150        _ => panic!("Invalid input {}", ch),
151    }
152}
153
154
155#[inline]
156fn is_octal_character(ch: u8) -> bool {
157    match ch {
158        b'0'...b'7' => true,
159        _ => false,
160    }
161}
162
163
164pub struct Parser<Iter: Iterator<Item=io::Result<u8>>> {
165    input : Iter,
166    line  : usize,
167    column: usize,
168    look  : Option<u8>,
169}
170
171
172macro_rules! try_no_eof {
173    ($obj:expr, $e:expr) => {
174        (match try!($e) {
175            None => return $obj.parse_error(ErrorCode::UnexpectedEOF),
176            Some(v) => v,
177        })
178    }
179}
180
181macro_rules! peek_no_eof {
182    ($e:expr) => {
183        match try!($e.peek()) {
184            None => return $e.parse_error(ErrorCode::UnexpectedEOF),
185            Some(v) => v,
186        }
187    }
188}
189
190macro_rules! getc_no_eof {
191    ($e:expr) => {
192        match $e.nextchar_raw() {
193            None => return $e.parse_error(ErrorCode::UnexpectedEOF),
194            Some(Err(error)) => return Err(Error::IoError(error)),
195            Some(Ok(ch)) => ch,
196        }
197    }
198}
199
200macro_rules! parse_digits {
201    ($e:expr, $base:expr, $check_digit:expr, $negative:expr) => {{
202        if !$check_digit(peek_no_eof!($e)) {
203            return $e.parse_error(ErrorCode::InvalidNumberValue);
204        }
205        let mut result = 0i64;
206        loop {
207            result = result * $base + match try!($e.peek()) {
208                Some(ch) if $check_digit(ch) => xdigit_to_int(ch) as i64,
209                Some(_) | None => break,
210            };
211            $e.advance();
212        }
213        if $negative {
214            result = -result;
215        }
216        Ok(Value::Integer(result))
217    }}
218}
219
220macro_rules! match_any {
221    ($e:expr, $error:ident, $($item:expr),+) => {
222        match peek_no_eof!($e) {
223            $(
224                $item => $e.advance(),
225            )*
226            _ => { return $e.parse_error(ErrorCode::$error); },
227        }
228    }
229}
230
231impl<Iter> Parser<Iter>
232    where Iter: Iterator<Item=io::Result<u8>>
233{
234    pub fn new(input: Iter) -> Self {
235        Parser {
236            input : input,
237            line  : 1,
238            column: 0,
239            look  : None,
240        }
241    }
242
243    fn nextchar_raw(&mut self) -> Option<io::Result<u8>> {
244        match self.input.next() {
245            Some(Ok(b'\n')) => {
246                self.line += 1;
247                self.column = 0;
248                Some(Ok(b'\n'))
249            }
250            Some(Ok(c)) => {
251                self.column += 1;
252                Some(Ok(c))
253            }
254            x => x,
255        }
256    }
257
258    fn nextchar(&mut self) -> Option<io::Result<u8>> {
259        match self.nextchar_raw() {
260            Some(Ok(b'#')) => loop {
261                match self.nextchar_raw() {
262                    None => return None,
263                    Some(Ok(b'\n')) => return self.nextchar(),
264                    Some(Ok(..)) => continue,
265                    Some(Err(x)) => return Some(Err(x)),
266                }
267            },
268            x => return x,
269        }
270    }
271
272    fn peek(&mut self) -> Result<Option<u8>> {
273        match self.look {
274            Some(ch) => Ok(Some(ch)),
275            None => {
276                match self.nextchar() {
277                    Some(Err(error)) => Err(Error::IoError(error)),
278                    Some(Ok(ch)) => {
279                        self.look = Some(ch);
280                        Ok(self.look)
281                    },
282                    None => Ok(None),
283                }
284            }
285        }
286    }
287
288    fn advance(&mut self) {
289        self.look = None;
290    }
291
292    fn parse_whitespace(&mut self) -> Result<()> {
293        match self.peek() {
294            Err(t) => Err(t),
295            Ok(None) => Ok(()),
296            Ok(Some(ch)) if is_whitespace_character(ch) => {
297                self.advance();
298                self.parse_whitespace()
299            },
300            Ok(Some(ch)) => {
301                self.look = Some(ch);
302                return Ok(())
303            },
304        }
305    }
306
307    fn parse_error<T>(&self, code : ErrorCode) -> Result<T> {
308        Err(Error::SyntaxError(code, self.line, self.column))
309    }
310
311    fn parse_value(&mut self) -> Result<Value> {
312        match peek_no_eof!(self) {
313            b'"' => self.parse_string(),
314            b'[' => self.parse_list(),
315            b'{' => self.parse_dict(),
316            b'T' | b't' | b'F' | b'f' => self.parse_bool(),
317            _ => self.parse_number(),
318        }
319    }
320
321    fn match_char(&mut self, expected: u8, code: ErrorCode) -> Result<()> {
322        if peek_no_eof!(self) == expected {
323            self.advance();
324            Ok(())
325        } else {
326            self.parse_error(code)
327        }
328    }
329
330    fn parse_string(&mut self) -> Result<Value> {
331        try!(self.match_char(b'"', ErrorCode::UnterminatedString));
332        let mut value = Vec::new();
333        loop {
334            match getc_no_eof!(self) {
335                b'"' => break,
336                b'\\' => match getc_no_eof!(self) {
337                    b'"'  => value.push(b'"'),
338                    b'\\' => value.push(b'\\'),
339                    b'n'  => value.push(b'\n'),
340                    b'r'  => value.push(b'\r'),
341                    b't'  => value.push(b'\t'),
342                    c if is_xdigit_character(c) => {
343                        // Hex code.
344                        let x = match getc_no_eof!(self) {
345                            ch if is_xdigit_character(ch) => ch,
346                            _ => return self.parse_error(ErrorCode::InvalidEscapeSequence),
347                        };
348                        value.push(xdigit_to_int(c) * 16 + xdigit_to_int(x));
349                    },
350                    _ => return self.parse_error(ErrorCode::InvalidEscapeSequence),
351                },
352                ch => value.push(ch),
353            }
354        }
355
356        match String::from_utf8(value) {
357            Err(_) => self.parse_error(ErrorCode::InvalidUtf8Sequence),
358            Ok(x) => Ok(Value::String(x)),
359        }
360    }
361
362    fn parse_list(&mut self) -> Result<Value> {
363        try!(self.match_char(b'[', ErrorCode::UnterminatedList));
364        try!(self.parse_whitespace());
365
366        let mut list = Vec::new();
367        while peek_no_eof!(self) != b']' {
368            // Parse a single value.
369            list.push(try!(self.parse_value()));
370
371            // There must be either comma or whitespace.
372            let got_whitespace = is_whitespace_character(peek_no_eof!(self));
373            try!(self.parse_whitespace());
374            if peek_no_eof!(self) == b',' {
375                self.advance();
376            } else if !got_whitespace && !is_whitespace_character(peek_no_eof!(self)) {
377                break;
378            }
379            try!(self.parse_whitespace());
380        }
381
382        try!(self.match_char(b']', ErrorCode::UnterminatedList));
383        Ok(Value::List(list))
384    }
385
386    fn parse_key(&mut self) -> Result<String> {
387        let mut key = Vec::new();
388        while is_key_character(peek_no_eof!(self)) {
389            key.push(peek_no_eof!(self));
390            self.advance();
391        }
392
393        if key.len() == 0 {
394            self.parse_error(ErrorCode::ExpectedDictKey)
395        } else {
396            match String::from_utf8(key) {
397                Err(_) => self.parse_error(ErrorCode::InvalidUtf8Sequence),
398                Ok(x) => Ok(x),
399            }
400        }
401    }
402
403    fn parse_keyval_items(&mut self, delim: Option<u8>) -> Result<Value> {
404        let mut items = BTreeMap::new();
405        while try!(self.peek()) != delim {
406            let key = try!(self.parse_key());
407            let mut got_separator = false;
408            if is_whitespace_character(peek_no_eof!(self)) {
409                try!(self.parse_whitespace());
410                got_separator = true;
411            }
412
413            match peek_no_eof!(self) {
414                b':' => {
415                    self.advance();
416                    try!(self.parse_whitespace());
417                    got_separator = true;
418                },
419                b'{' | b'[' => {
420                    got_separator = true;
421                },
422                _ => (),
423            }
424            if !got_separator {
425                return self.parse_error(ErrorCode::ExpectedSeparator);
426            }
427
428            items.insert(key, try!(self.parse_value()));
429
430            match try!(self.peek()) {
431                Some(b',') => self.advance(),
432                Some(ch) if Some(ch) != delim =>
433                    if !is_whitespace_character(ch) {
434                        break;
435                    },
436                None if None != delim =>
437                    return self.parse_error(ErrorCode::UnexpectedEOF),
438                _ => (),
439            }
440
441            try!(self.parse_whitespace());
442        }
443        Ok(Value::Dict(items))
444    }
445
446    fn parse_dict(&mut self) -> Result<Value> {
447        try!(self.match_char(b'{', ErrorCode::UnterminatedDict));
448        try!(self.parse_whitespace());
449        let result = try!(self.parse_keyval_items(Some(b'}')));
450        try!(self.match_char(b'}', ErrorCode::UnterminatedDict));
451        Ok(result)
452    }
453
454    fn parse_bool_rest(&mut self, result: bool) -> Result<Value> {
455        self.advance();
456        let remaining : &[u8] = { if result { b"rue" } else { b"alse" } };
457        for byte in remaining {
458            if peek_no_eof!(self) != *byte {
459                return self.parse_error(ErrorCode::InvalidBoolValue);
460            }
461            self.advance();
462        }
463        Ok(Value::Bool(result))
464    }
465
466    fn parse_bool(&mut self) -> Result<Value> {
467        match peek_no_eof!(self) {
468            b'T' | b't' => self.parse_bool_rest(true),
469            b'F' | b'f' => self.parse_bool_rest(false),
470            _ => self.parse_error(ErrorCode::InvalidBoolValue),
471        }
472    }
473
474    fn parse_number(&mut self) -> Result<Value> {
475        let mut buffer = Vec::new();
476
477        // Optional sign.
478        let negative = match peek_no_eof!(self) {
479            b'-' => { self.advance(); true },
480            b'+' => { self.advance(); false },
481            _ => false,
482        };
483
484        // Detect octal/hex/nan/inf numbers.
485        match peek_no_eof!(self) {
486            b'0' => {
487                buffer.push(b'0');
488                self.advance();
489                match try!(self.peek()) {
490                    None => (),
491                    Some(b'x') | Some(b'X') => {
492                        buffer.push(b'x');
493                        self.advance();
494                        return parse_digits!(self, 16, is_xdigit_character, negative)
495                    },
496                    Some(ch) if is_octal_character(ch) =>
497                        return parse_digits!(self, 8, is_octal_character, negative),
498                    Some(_) => (),
499                }
500            },
501            b'N' | b'n' => {
502                self.advance();
503                match_any!(self, InvalidNumberValue, b'a', b'A');
504                match_any!(self, InvalidNumberValue, b'n', b'N');
505                return Ok(Value::Float(if negative { -NAN } else { NAN }));
506            },
507            b'I' | b'i' => {
508                self.advance();
509                match_any!(self, InvalidNumberValue, b'n', b'N');
510                match_any!(self, InvalidNumberValue, b'f', b'F');
511                match try!(self.peek()) {
512                    Some(b'i') | Some(b'I') => {
513                        self.advance();
514                        match_any!(self, InvalidNumberValue, b'n', b'N');
515                        match_any!(self, InvalidNumberValue, b'i', b'I');
516                        match_any!(self, InvalidNumberValue, b't', b'T');
517                        match_any!(self, InvalidNumberValue, b'y', b'Y');
518                    }
519                    _ => (),
520                }
521                return Ok(Value::Float(if negative { -INFINITY } else { INFINITY }));
522            },
523            _ => (),
524        }
525
526        let mut dot_seen = false;
527        let mut exp_seen = false;
528        loop {
529            match try!(self.peek()) {
530                None => break,
531                Some(b'e') | Some(b'E') => {
532                    if exp_seen {
533                        return self.parse_error(ErrorCode::InvalidNumberValue);
534                    }
535                    exp_seen = true;
536                    buffer.push(b'e');
537                    self.advance();
538                    // Optional exponent sign.
539                    match peek_no_eof!(self) {
540                        ch @b'-' | ch @b'+' => {
541                            buffer.push(ch);
542                            self.advance();
543                        },
544                        _ => (),
545                    }
546                },
547                Some(b'.') => {
548                    if dot_seen {
549                        return self.parse_error(ErrorCode::InvalidNumberValue);
550                    }
551                    dot_seen = true;
552                    buffer.push(b'.');
553                    self.advance();
554                },
555                Some(ch @b'0'...b'9') => {
556                    buffer.push(ch);
557                    self.advance();
558                },
559                Some(_) =>
560                    return self.parse_error(ErrorCode::InvalidNumberValue),
561            }
562        }
563
564        if buffer.len() == 0 {
565            return self.parse_error(ErrorCode::InvalidNumberValue);
566        }
567
568        let string_value = match String::from_utf8(buffer) {
569            Err(_) => return self.parse_error(ErrorCode::InvalidUtf8Sequence),
570            Ok(value) => value,
571        };
572
573        if dot_seen || exp_seen {
574            match string_value.parse::<f64>() {
575                Ok(value) => Ok(Value::Float(if negative { -value } else { value })),
576                Err(_) => self.parse_error(ErrorCode::InvalidNumberValue),
577            }
578        } else {
579            match string_value.parse::<i64>() {
580                Ok(value) => Ok(Value::Integer(if negative { -value } else { value })),
581                Err(_) => self.parse_error(ErrorCode::InvalidNumberValue),
582            }
583        }
584    }
585
586    pub fn parse_message(&mut self) -> Result<Value> {
587        try!(self.parse_whitespace());
588        match try!(self.peek()) {
589            None => Ok(Value::Dict(BTreeMap::new())),
590            Some(b'{') => {
591                self.advance();
592                try!(self.parse_whitespace());
593                let result = try!(self.parse_keyval_items(Some(b'}')));
594                try!(self.match_char(b'}', ErrorCode::UnterminatedMessage));
595                Ok(result)
596            },
597            _ => self.parse_keyval_items(None),
598        }
599    }
600}
601
602
603#[cfg(test)]
604mod tests {
605	use super::*;
606	use super::super::value::Value;
607	use std::io::{Cursor, Read};
608
609	#[test]
610	fn peek_input() {
611	    let input = Cursor::new("Hello, world".as_bytes());
612	    let mut p = Parser::new(input.bytes());
613	    assert_eq!(Some(b'H'), p.peek().unwrap());
614	}
615
616	#[test]
617	fn ignore_comment() {
618	    let input = Cursor::new("# Comment\nFoo".as_bytes());
619	    let mut p = Parser::new(input.bytes());
620	    assert_eq!(Some(b'F'), p.peek().unwrap());
621    }
622
623    #[test]
624    fn ignore_consecutive_comments() {
625        let input = Cursor::new("# Comment 1\n#Comment 2\nBar".as_bytes());
626        let mut p = Parser::new(input.bytes());
627        assert_eq!(Some(b'B'), p.peek().unwrap());
628    }
629
630    #[test]
631    fn skip_whitespace() {
632        let input = Cursor::new("    Whitespace".as_bytes());
633        let mut p = Parser::new(input.bytes());
634        p.parse_whitespace().unwrap();
635        assert_eq!(Some(b'W'), p.peek().unwrap());
636    }
637
638    #[test]
639    fn advance_input() {
640        let hello = "Hello, world";
641        let mut check = hello.bytes();
642        let input = Cursor::new(hello.as_bytes());
643        let mut p = Parser::new(input.bytes());
644        loop {
645            match p.peek().unwrap() {
646                Some(ch) => assert_eq!(check.next().unwrap(), ch),
647                None => break,
648            }
649            p.advance();
650        }
651    }
652
653    macro_rules! make_fail_tests {
654        ($($name:ident, $str:expr),+) => {
655            $(
656            #[test] #[should_panic]
657            fn $name() {
658                let input = Cursor::new($str.as_bytes());
659                let mut p = Parser::new(input.bytes());
660                p.parse_list().unwrap().as_list();
661            }
662            )*
663        }
664    }
665
666    macro_rules! make_bool_tests {
667        ($expected:expr, $($name:ident, $str:expr),+) => {
668            $(
669            #[test]
670            fn $name() {
671                let input = Cursor::new($str.as_bytes());
672                let mut p = Parser::new(input.bytes());
673                assert_eq!(Some($expected), p.parse_bool().unwrap().as_bool());
674            }
675            )*
676        }
677    }
678
679    make_bool_tests!(true,
680                     parse_true,       "true",
681                     parse_true_upper, "True");
682    make_bool_tests!(false,
683                     parse_false,       "false",
684                     parse_false_upper, "False");
685    make_fail_tests!(parse_true_allupper,  "TRUE",
686                     parse_false_allupper, "FALSE");
687
688
689    macro_rules! make_list_test {
690        ($name:ident, $value:ident, $str:expr, $block:block) => {
691            #[test]
692            fn $name() {
693                let input = Cursor::new($str.as_bytes());
694                let mut p = Parser::new(input.bytes());
695                if let Some($value) = p.parse_list().unwrap().as_list() {
696                    $block
697                } else {
698                    panic!("Parsing did not return a value");
699                }
700            }
701        }
702    }
703
704    make_list_test!(list_empty, value, "[]", {
705        assert_eq!(0, value.len());
706    });
707
708    make_list_test!(list_empty_space, value, "[  ]", {
709        assert_eq!(0, value.len());
710    });
711
712    make_list_test!(list_one_item, value, "[true]", {
713        assert_eq!(1, value.len());
714        assert_eq!(Some(true), value[0].as_bool());
715    });
716
717    make_list_test!(list_two_items_comma, value, "[true,false]", {
718        assert_eq!(2, value.len());
719        assert_eq!(Some(true), value[0].as_bool());
720        assert_eq!(Some(false), value[1].as_bool());
721    });
722
723    make_list_test!(list_two_items_space, value, "[true false]", {
724        assert_eq!(2, value.len());
725        assert_eq!(Some(true), value[0].as_bool());
726        assert_eq!(Some(false), value[1].as_bool());
727    });
728
729    make_list_test!(list_two_items_commaspace, value, "[true, false]", {
730        assert_eq!(2, value.len());
731        assert_eq!(Some(true), value[0].as_bool());
732        assert_eq!(Some(false), value[1].as_bool());
733    });
734
735    make_list_test!(list_two_items_spacecommaspace, value, "[true , false]", {
736        assert_eq!(2, value.len());
737        assert_eq!(Some(true), value[0].as_bool());
738        assert_eq!(Some(false), value[1].as_bool());
739    });
740
741    make_fail_tests!(list_unterminated, "[",
742                     list_unterminated_space, "[  ",
743                     list_unterminated_one_item, "[true",
744                     list_unterminated_one_item_space, "[true ",
745                     list_unterminated_one_item_comma, "[true,",
746                     list_unterminated_one_item_commaspace, "[true, ",
747                     list_unterminated_one_item_spacecommaspace, "[true , ");
748
749
750    macro_rules! make_dict_test {
751        ($name:ident, $value:ident, $str:expr, $block:block) => {
752            #[test]
753            fn $name() {
754                let input = Cursor::new($str.as_bytes());
755                let mut p = Parser::new(input.bytes());
756                if let Some($value) = p.parse_dict().unwrap().as_dict() {
757                    $block
758                } else {
759                    panic!("Parsing did not return a value");
760                }
761            }
762        }
763    }
764
765    make_dict_test!(dict_empty, value, "{}", {
766        assert_eq!(0, value.len());
767    });
768    make_dict_test!(dict_empty_space, value, "{  }", {
769        assert_eq!(0, value.len());
770    });
771    make_dict_test!(dict_one_item, value, "{ a: True }", {
772        assert_eq!(1, value.len());
773        assert!(value.contains_key("a"));
774        assert_eq!(Some(true), value.get("a").unwrap().as_bool());
775    });
776    make_dict_test!(dict_one_item_space, value, "{a False}", {
777        assert_eq!(1, value.len());
778        assert!(value.contains_key("a"));
779        assert_eq!(Some(false), value.get("a").unwrap().as_bool());
780    });
781    make_dict_test!(dict_two_items, value, "{a:true,b:false}", {
782        assert_eq!(2, value.len());
783        assert_eq!(true, value.get("a").unwrap().as_bool().unwrap());
784        assert_eq!(false, value.get("b").unwrap().as_bool().unwrap());
785    });
786    make_dict_test!(dict_two_items_space, value, "{a:true b:false}", {
787        assert_eq!(2, value.len());
788        assert_eq!(true, value.get("a").unwrap().as_bool().unwrap());
789        assert_eq!(false, value.get("b").unwrap().as_bool().unwrap());
790    });
791    make_dict_test!(dict_two_items_commaspace, value, "{a:true, b:false}", {
792        assert_eq!(2, value.len());
793        assert_eq!(true, value.get("a").unwrap().as_bool().unwrap());
794        assert_eq!(false, value.get("b").unwrap().as_bool().unwrap());
795    });
796
797    make_fail_tests!(dict_unterminated, "{",
798                     dict_unterminated_with_key, "{ key",
799                     dict_unterminated_with_key_space, "{ key ",
800                     dict_unterminated_with_key_colon, "{ key:",
801                     dict_unterminated_with_key_colonspace, "{ key: ",
802                     dict_missing_value, "{ key }",
803                     dict_missing_value_colon, "{ key: }");
804
805
806    macro_rules! make_string_tests {
807        ($($name:ident, $str:expr, $expected:expr),+) => {
808            $(
809            #[test]
810            fn $name() {
811                let input = Cursor::new($str.as_bytes());
812                let mut p = Parser::new(input.bytes());
813                assert_eq!($expected, p.parse_string().unwrap().as_string().unwrap());
814            }
815            )*
816        }
817    }
818
819    make_string_tests!(string_empty, "\"\"", "",
820                       string_foo_bar, "\"foo bar\"", "foo bar",
821                       string_unicode, "\"☺\"", "☺");
822
823    macro_rules! make_number_tests {
824        ($t:ident, $($name:ident, $str:expr, $expected:expr),+) => {
825            $(
826            #[test]
827            fn $name() {
828                let mut p = Parser::new(Cursor::new($str.as_bytes()).bytes());
829                match p.parse_number().unwrap() {
830                    Value::$t(value) => assert_eq!($expected, value),
831                    _ => panic!("{} decoded into in incorrect type", stringify!($t)),
832                }
833            }
834            )*
835        }
836    }
837
838    make_number_tests!(Integer,
839                       integer_zero, "0", 0,
840                       integer_zero_octal, "00", 0,
841                       integer_zero_hex, "0x0", 0,
842                       integer_negative, "-42", -42,
843                       integer_signed, "+42", 42,
844                       integer_hex, "0xCAFE", 0xCAFE,
845                       integer_octal, "01744", 0o1744,
846                       integer_negative_oct, "-0644", -0o644);
847
848    make_number_tests!(Float,
849                       float_zero, "0.0", 0f64,
850                       float_zero_exp, "0e0", 0f64,
851                       float_zero_negative, "-0.0", -0f64,
852                       float_exp_negative, "1e-0", 1e-0_f64,
853                       float_negative_exp_negative, "-1e-0", -1e0_f64);
854
855    macro_rules! make_exotic_float_tests {
856        ($check:ident, $name:ident, $($str:expr),+) => {
857            #[test]
858            fn $name() {
859                $({
860                    println!($str);
861                    let mut p = Parser::new(Cursor::new($str.as_bytes()).bytes());
862                    assert!(p.parse_number().unwrap().as_float().unwrap().$check());
863                })*
864            }
865        }
866    }
867
868    make_exotic_float_tests!(is_nan, float_nan, "NaN", "nan", "NAN", "nAn", "nAN", "Nan");
869    make_exotic_float_tests!(is_infinite, float_inf, "Inf", "inf", "iNf", "iNF",
870                             "Infinity", "infinity", "iNfInItY", "iNFiniTy");
871}