Skip to content

Commit 6c7f103

Browse files
committed
Fixes #93
1 parent feb364a commit 6c7f103

File tree

5 files changed

+191
-125
lines changed

5 files changed

+191
-125
lines changed

src/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub enum Error {
1313
column: usize,
1414
},
1515
UnexpectedEndOfJson,
16+
ExceededDepthLimit,
1617
FailedUtf8Parsing,
1718
WrongType(String),
1819
}
@@ -35,6 +36,7 @@ impl fmt::Display for Error {
3536
} => write!(f, "Unexpected character: {} at ({}:{})", ch, line, column),
3637

3738
UnexpectedEndOfJson => write!(f, "Unexpected end of JSON"),
39+
ExceededDepthLimit => write!(f, "Exceeded depth limit"),
3840
FailedUtf8Parsing => write!(f, "Failed to parse UTF-8 bytes"),
3941
WrongType(ref s) => write!(f, "Wrong type, expected: {}", s),
4042
}
@@ -44,9 +46,11 @@ impl fmt::Display for Error {
4446
impl error::Error for Error {
4547
fn description(&self) -> &str {
4648
use Error::*;
49+
4750
match *self {
4851
UnexpectedCharacter { .. } => "Unexpected character",
4952
UnexpectedEndOfJson => "Unexpected end of JSON",
53+
ExceededDepthLimit => "Exceeded depth limit",
5054
FailedUtf8Parsing => "Failed to read bytes as UTF-8 from JSON",
5155
WrongType(_) => "Wrong type",
5256
}

src/object.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,13 @@ impl Object {
339339
}
340340
}
341341

342+
#[inline]
343+
pub fn override_last(&mut self, value: JsonValue) {
344+
if let Some(node) = self.store.last_mut() {
345+
node.value = value;
346+
}
347+
}
348+
342349
pub fn get(&self, key: &str) -> Option<&JsonValue> {
343350
if self.store.len() == 0 {
344351
return None;

src/parser.rs

Lines changed: 136 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// This makes for some ugly code, but it is faster. Hopefully in the future
1818
// with MIR support the compiler will get smarter about this.
1919

20-
use std::{ ptr, mem, str, slice, char };
20+
use std::{ str, slice, char };
2121
use object::Object;
2222
use number::Number;
2323
use { JsonValue, Error, Result };
@@ -27,6 +27,10 @@ use { JsonValue, Error, Result };
2727
const MAX_PRECISION: u64 = 576460752303423500;
2828

2929

30+
// How many nested Objects/Arrays are allowed to be parsed
31+
const DEPTH_LIMIT: usize = 512;
32+
33+
3034
// Position is only used when we stumble upon an unexpected character. We don't
3135
// track lines during parsing, as that would mean doing unnecessary work.
3236
// Instead, if an error occurs, we figure out the line and column from the
@@ -121,6 +125,20 @@ macro_rules! expect_byte_ignore_whitespace {
121125
})
122126
}
123127

128+
// Expect to find EOF or just whitespaces leading to EOF after a JSON value
129+
macro_rules! expect_eof {
130+
($parser:ident) => ({
131+
while !$parser.is_eof() {
132+
match $parser.read_byte() {
133+
9 ... 13 | 32 => $parser.bump(),
134+
ch => {
135+
$parser.bump();
136+
return $parser.unexpected_character(ch);
137+
}
138+
}
139+
}
140+
})
141+
}
124142

125143
// Expect a particular byte to be next. Also available with a variant
126144
// creates a `match` expression just to ease some pain.
@@ -350,52 +368,6 @@ macro_rules! expect_fraction {
350368
})
351369
}
352370

353-
354-
// This is where the magic happens. This macro will read from the source
355-
// and try to create an instance of `JsonValue`. Note that it only reads
356-
// bytes that _begin_ a JSON value, however it can also accept an optional
357-
// pattern with custom logic. This is used in arrays, which expect either
358-
// a value or a closing bracket `b"]"`.
359-
macro_rules! expect_value {
360-
{$parser:ident $(, $byte:pat => $then:expr )*} => ({
361-
let ch = expect_byte_ignore_whitespace!($parser);
362-
363-
match ch {
364-
$(
365-
$byte => $then,
366-
)*
367-
b'[' => JsonValue::Array(try!($parser.read_array())),
368-
b'{' => JsonValue::Object(try!($parser.read_object())),
369-
b'"' => expect_string!($parser).into(),
370-
b'0' => JsonValue::Number(allow_number_extensions!($parser)),
371-
b'1' ... b'9' => {
372-
JsonValue::Number(expect_number!($parser, ch))
373-
},
374-
b'-' => {
375-
let ch = expect_byte!($parser);
376-
JsonValue::Number(- match ch {
377-
b'0' => allow_number_extensions!($parser),
378-
b'1' ... b'9' => expect_number!($parser, ch),
379-
_ => return $parser.unexpected_character(ch)
380-
})
381-
}
382-
b't' => {
383-
expect_sequence!($parser, b'r', b'u', b'e');
384-
JsonValue::Boolean(true)
385-
},
386-
b'f' => {
387-
expect_sequence!($parser, b'a', b'l', b's', b'e');
388-
JsonValue::Boolean(false)
389-
},
390-
b'n' => {
391-
expect_sequence!($parser, b'u', b'l', b'l');
392-
JsonValue::Null
393-
},
394-
_ => return $parser.unexpected_character(ch)
395-
}
396-
})
397-
}
398-
399371
impl<'a> Parser<'a> {
400372
pub fn new(source: &'a str) -> Self {
401373
Parser {
@@ -704,102 +676,146 @@ impl<'a> Parser<'a> {
704676
Ok(Number::from_parts(true, num, (big_e.saturating_add(e * sign))))
705677
}
706678

707-
// Given how compilcated reading numbers and strings is, reading objects
708-
// is actually pretty simple.
709-
fn read_object(&mut self) -> Result<Object> {
710-
let key = expect!{ self,
711-
b'}' => return Ok(Object::new()),
712-
b'\"' => expect_string!(self)
713-
};
679+
// Parse away!
680+
fn parse(&mut self) -> Result<JsonValue> {
681+
let mut stack = Vec::with_capacity(3);
682+
let mut ch = expect_byte_ignore_whitespace!(self);
714683

715-
let mut object = Object::with_capacity(3);
684+
'parsing: loop {
685+
let mut value = match ch {
686+
b'[' => {
687+
ch = expect_byte_ignore_whitespace!(self);
716688

717-
expect!(self, b':');
689+
if ch != b']' {
690+
if stack.len() == DEPTH_LIMIT {
691+
return Err(Error::ExceededDepthLimit);
692+
}
718693

719-
object.insert(key, expect_value!(self));
694+
stack.push(StackBlock::Array(Vec::with_capacity(2)));
695+
continue 'parsing;
696+
}
720697

721-
loop {
722-
let key = expect!{ self,
723-
b'}' => break,
724-
b',' => {
725-
expect!(self, b'"');
726-
expect_string!(self)
698+
JsonValue::Array(Vec::new())
699+
},
700+
b'{' => {
701+
ch = expect_byte_ignore_whitespace!(self);
702+
703+
if ch != b'}' {
704+
if stack.len() == DEPTH_LIMIT {
705+
return Err(Error::ExceededDepthLimit);
706+
}
707+
708+
let mut object = Object::with_capacity(3);
709+
710+
if ch != b'"' {
711+
return self.unexpected_character(ch)
712+
}
713+
714+
object.insert(expect_string!(self), JsonValue::Null);
715+
expect!(self, b':');
716+
717+
stack.push(StackBlock::Object(object));
718+
719+
ch = expect_byte_ignore_whitespace!(self);
720+
721+
continue 'parsing;
722+
}
723+
724+
JsonValue::Object(Object::new())
725+
},
726+
b'"' => expect_string!(self).into(),
727+
b'0' => JsonValue::Number(allow_number_extensions!(self)),
728+
b'1' ... b'9' => {
729+
JsonValue::Number(expect_number!(self, ch))
730+
},
731+
b'-' => {
732+
let ch = expect_byte!(self);
733+
JsonValue::Number(- match ch {
734+
b'0' => allow_number_extensions!(self),
735+
b'1' ... b'9' => expect_number!(self, ch),
736+
_ => return self.unexpected_character(ch)
737+
})
727738
}
739+
b't' => {
740+
expect_sequence!(self, b'r', b'u', b'e');
741+
JsonValue::Boolean(true)
742+
},
743+
b'f' => {
744+
expect_sequence!(self, b'a', b'l', b's', b'e');
745+
JsonValue::Boolean(false)
746+
},
747+
b'n' => {
748+
expect_sequence!(self, b'u', b'l', b'l');
749+
JsonValue::Null
750+
},
751+
_ => return self.unexpected_character(ch)
728752
};
729753

730-
expect!(self, b':');
754+
'popping: loop {
755+
match stack.pop() {
756+
None => {
757+
expect_eof!(self);
731758

732-
object.insert(key, expect_value!(self));
733-
}
759+
return Ok(value);
760+
},
734761

735-
Ok(object)
736-
}
762+
Some(StackBlock::Array(mut array)) => {
763+
array.push(value);
737764

738-
// And reading arrays is simpler still!
739-
fn read_array(&mut self) -> Result<Vec<JsonValue>> {
740-
let first = expect_value!{ self, b']' => return Ok(Vec::new()) };
765+
ch = expect_byte_ignore_whitespace!(self);
741766

742-
let mut array = Vec::with_capacity(2);
767+
match ch {
768+
b',' => {
769+
stack.push(StackBlock::Array(array));
743770

744-
unsafe {
745-
// First member can be written to the array without any checks!
746-
ptr::copy_nonoverlapping(
747-
&first as *const JsonValue,
748-
array.as_mut_ptr(),
749-
1
750-
);
751-
mem::forget(first);
752-
array.set_len(1);
753-
}
771+
ch = expect_byte_ignore_whitespace!(self);
754772

755-
expect!{
756-
self,
757-
b']' => return Ok(array),
758-
b',' => {
759-
// Same for the second one!
760-
let value = expect_value!(self);
761-
unsafe {
762-
ptr::copy_nonoverlapping(
763-
&value as *const JsonValue,
764-
array.as_mut_ptr().offset(1),
765-
1
766-
);
767-
mem::forget(value);
768-
array.set_len(2);
769-
}
770-
}
771-
}
773+
continue 'parsing;
774+
},
775+
b']' => {
776+
value = JsonValue::Array(array);
777+
continue 'popping;
778+
},
779+
_ => return self.unexpected_character(ch)
780+
}
781+
},
772782

773-
loop {
774-
expect!{ self,
775-
b']' => break,
776-
b',' => array.push(expect_value!(self))
777-
};
778-
}
783+
Some(StackBlock::Object(mut object)) => {
784+
object.override_last(value);
779785

780-
Ok(array)
781-
}
786+
ch = expect_byte_ignore_whitespace!(self);
782787

783-
// Parse away!
784-
fn parse(&mut self) -> Result<JsonValue> {
785-
let value = expect_value!(self);
788+
match ch {
789+
b',' => {
790+
expect!(self, b'"');
791+
object.insert(expect_string!(self), JsonValue::Null);
792+
expect!(self, b':');
786793

787-
// We have read whatever value was there, but we need to make sure
788-
// there is nothing left to read - if there is, that's an error.
789-
while !self.is_eof() {
790-
match self.read_byte() {
791-
9 ... 13 | 32 => self.bump(),
792-
ch => {
793-
self.bump();
794-
return self.unexpected_character(ch);
794+
stack.push(StackBlock::Object(object));
795+
796+
ch = expect_byte_ignore_whitespace!(self);
797+
798+
continue 'parsing;
799+
},
800+
b'}' => {
801+
value = JsonValue::Object(object);
802+
803+
continue 'popping;
804+
},
805+
_ => return self.unexpected_character(ch)
806+
}
807+
},
795808
}
796809
}
797810
}
798-
799-
Ok(value)
800811
}
801812
}
802813

814+
enum StackBlock {
815+
Array(Vec<JsonValue>),
816+
Object(Object),
817+
}
818+
803819
// All that hard work, and in the end it's just a single function in the API.
804820
#[inline]
805821
pub fn parse(source: &str) -> Result<JsonValue> {

tests/json_checker.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ mod json_checker_pass {
165165

166166
#[test]
167167
fn pass_1() {
168-
assert!(parse(r##"
168+
parse(r##"
169169
170170
[
171171
"JSON Test Pattern pass1",
@@ -226,17 +226,21 @@ mod json_checker_pass {
226226
1e00,2e+00,2e-00
227227
,"rosebud"]
228228
229-
"##).is_ok());
229+
"##).unwrap();
230+
231+
assert!(true);
230232
}
231233

232234
#[test]
233235
fn pass_2() {
234-
assert!(parse(r#"[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]"#).is_ok());
236+
parse(r#"[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]"#).unwrap();
237+
238+
assert!(true);
235239
}
236240

237241
#[test]
238242
fn pass_3() {
239-
assert!(parse(r#"
243+
parse(r#"
240244
241245
{
242246
"JSON Test Pattern pass3": {
@@ -245,6 +249,8 @@ mod json_checker_pass {
245249
}
246250
}
247251
248-
"#).is_ok());
252+
"#).unwrap();
253+
254+
assert!(true);
249255
}
250256
}

0 commit comments

Comments
 (0)