Skip to content

Commit 74626cd

Browse files
authored
allow to enforce max nest level (#10)
* allow to enforce max nest level * cargo fmt
1 parent 1590278 commit 74626cd

File tree

3 files changed

+274
-56
lines changed

3 files changed

+274
-56
lines changed

src/json.rs

Lines changed: 95 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ extern crate alloc;
55
use alloc::vec::Vec;
66

77
use crate::parser::{
8-
Concat, Concat3, Either, Error, Input, OneOf, OneOrMore, Parser, ResultOf, ZeroOrMore,
9-
ZeroOrOne,
8+
Concat, Concat3, Either, Error, Input, OneOf, OneOrMore, Parser, ParserContext, ResultOf,
9+
ZeroOrMore, ZeroOrOne,
1010
};
1111
use crate::{literals, parsers};
1212
use core::convert::TryInto;
@@ -117,17 +117,21 @@ pub struct Escape;
117117

118118
impl<I: Input> Parser<I> for Escape {
119119
type Output = char;
120-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
120+
fn parse(
121+
input: &I,
122+
current: I::Position,
123+
context: &ParserContext,
124+
) -> ResultOf<I, Self::Output> {
121125
let (c, next) = input
122126
.next(current)
123127
.map_err(|e| e.add_reason(current, "Escape"))?;
124128
match c {
125129
'"' | '\\' | '/' | 'b' | 'f' | 'n' | 'r' | 't' => Ok((c, next)),
126130
'u' => {
127-
let (b1, next) = <Hex as Parser<I>>::parse(input, next)?;
128-
let (b2, next) = <Hex as Parser<I>>::parse(input, next)?;
129-
let (b3, next) = <Hex as Parser<I>>::parse(input, next)?;
130-
let (b4, next) = <Hex as Parser<I>>::parse(input, next)?;
131+
let (b1, next) = <Hex as Parser<I>>::parse(input, next, context)?;
132+
let (b2, next) = <Hex as Parser<I>>::parse(input, next, context)?;
133+
let (b3, next) = <Hex as Parser<I>>::parse(input, next, context)?;
134+
let (b4, next) = <Hex as Parser<I>>::parse(input, next, context)?;
131135
let byte = (b1 as u32) << 24 | (b2 as u32) << 16 | (b3 as u32) << 8 | (b4 as u32);
132136
let c = byte
133137
.try_into()
@@ -143,12 +147,16 @@ pub struct Character;
143147

144148
impl<I: Input> Parser<I> for Character {
145149
type Output = char;
146-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
150+
fn parse(
151+
input: &I,
152+
current: I::Position,
153+
context: &ParserContext,
154+
) -> ResultOf<I, Self::Output> {
147155
let (c, next) = input
148156
.next(current)
149157
.map_err(|e| e.add_reason(current, "Character"))?;
150158
match c {
151-
'\\' => <Escape as Parser<I>>::parse(input, next),
159+
'\\' => <Escape as Parser<I>>::parse(input, next, context),
152160
'"' => Err(input.error_at(current, "Character")),
153161
_ => Ok((c, next)),
154162
}
@@ -161,10 +169,14 @@ pub struct Member;
161169

162170
impl<I: Input> Parser<I> for Member {
163171
type Output = (Vec<char>, JsonValue);
164-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
165-
let (_, next) = <Whitespace as Parser<I>>::parse(input, current)?;
166-
let (key, next) = <String as Parser<I>>::parse(input, next)?;
167-
let (_, next) = <Whitespace as Parser<I>>::parse(input, next)?;
172+
fn parse(
173+
input: &I,
174+
current: I::Position,
175+
context: &ParserContext,
176+
) -> ResultOf<I, Self::Output> {
177+
let (_, next) = <Whitespace as Parser<I>>::parse(input, current, context)?;
178+
let (key, next) = <String as Parser<I>>::parse(input, next, context)?;
179+
let (_, next) = <Whitespace as Parser<I>>::parse(input, next, context)?;
168180
let next = input
169181
.next(next)
170182
.and_then(|(c, next)| {
@@ -175,7 +187,7 @@ impl<I: Input> Parser<I> for Member {
175187
}
176188
})
177189
.map_err(|e| e.add_reason(current, "Member"))?;
178-
let (value, next) = <Element as Parser<I>>::parse(input, next)?;
190+
let (value, next) = <Element as Parser<I>>::parse(input, next, context)?;
179191
Ok(((key, value), next))
180192
}
181193
}
@@ -184,10 +196,14 @@ pub struct Element;
184196

185197
impl<I: Input> Parser<I> for Element {
186198
type Output = JsonValue;
187-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
188-
let (_, next) = <Whitespace as Parser<I>>::parse(input, current)?;
189-
let (output, next) = <Value as Parser<I>>::parse(input, next)?;
190-
let (_, next) = <Whitespace as Parser<I>>::parse(input, next)?;
199+
fn parse(
200+
input: &I,
201+
current: I::Position,
202+
context: &ParserContext,
203+
) -> ResultOf<I, Self::Output> {
204+
let (_, next) = <Whitespace as Parser<I>>::parse(input, current, context)?;
205+
let (output, next) = <Value as Parser<I>>::parse(input, next, context)?;
206+
let (_, next) = <Whitespace as Parser<I>>::parse(input, next, context)?;
191207
Ok((output, next))
192208
}
193209
}
@@ -238,17 +254,21 @@ where
238254
I::Position: Copy,
239255
{
240256
type Output = JsonValue;
241-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
242-
if let Ok((output, next)) = <Object as Parser<I>>::parse(input, current) {
257+
fn parse(
258+
input: &I,
259+
current: I::Position,
260+
context: &ParserContext,
261+
) -> ResultOf<I, Self::Output> {
262+
if let Ok((output, next)) = <Object as Parser<I>>::parse(input, current, context) {
243263
return Ok((JsonValue::Object(output), next));
244264
}
245-
if let Ok((output, next)) = <Array as Parser<I>>::parse(input, current) {
265+
if let Ok((output, next)) = <Array as Parser<I>>::parse(input, current, context) {
246266
return Ok((JsonValue::Array(output), next));
247267
}
248-
if let Ok((output, next)) = <String as Parser<I>>::parse(input, current) {
268+
if let Ok((output, next)) = <String as Parser<I>>::parse(input, current, context) {
249269
return Ok((JsonValue::String(output), next));
250270
}
251-
if let Ok((output, next)) = <Number as Parser<I>>::parse(input, current) {
271+
if let Ok((output, next)) = <Number as Parser<I>>::parse(input, current, context) {
252272
return Ok((JsonValue::Number(output), next));
253273
}
254274
let (value, next) = input.next_range(current, 4)?;
@@ -272,10 +292,16 @@ type JsonObject = Vec<(Vec<char>, JsonValue)>;
272292

273293
impl<I: Input> Parser<I> for Object {
274294
type Output = JsonObject;
275-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
276-
let (_, next) = <OpenCurlyBracketChar as Parser<I>>::parse(input, current)?;
277-
let (output, next) = <OneOf<Members, Whitespace> as Parser<I>>::parse(input, next)?;
278-
let (_, next) = <CloseCurlyBracketChar as Parser<I>>::parse(input, next)?;
295+
fn parse(
296+
input: &I,
297+
current: I::Position,
298+
context: &ParserContext,
299+
) -> ResultOf<I, Self::Output> {
300+
let context = &context.nest(input, current)?;
301+
let (_, next) = <OpenCurlyBracketChar as Parser<I>>::parse(input, current, context)?;
302+
let (output, next) =
303+
<OneOf<Members, Whitespace> as Parser<I>>::parse(input, next, context)?;
304+
let (_, next) = <CloseCurlyBracketChar as Parser<I>>::parse(input, next, context)?;
279305
let output = match output {
280306
Either::A(a) => a,
281307
Either::B(_) => Vec::new(),
@@ -288,10 +314,14 @@ pub struct Members;
288314

289315
impl<I: Input> Parser<I> for Members {
290316
type Output = Vec<(Vec<char>, JsonValue)>;
291-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
292-
let (output, next) = <Member as Parser<I>>::parse(input, current)?;
317+
fn parse(
318+
input: &I,
319+
current: I::Position,
320+
context: &ParserContext,
321+
) -> ResultOf<I, Self::Output> {
322+
let (output, next) = <Member as Parser<I>>::parse(input, current, context)?;
293323
let (rest, next) =
294-
<ZeroOrMore<Concat<CommaChar, Member>> as Parser<I>>::parse(input, next)?;
324+
<ZeroOrMore<Concat<CommaChar, Member>> as Parser<I>>::parse(input, next, context)?;
295325
let mut result = Vec::new();
296326
result.push(output);
297327
if let Either::A(rest) = rest {
@@ -305,10 +335,14 @@ pub struct Elements;
305335

306336
impl<I: Input> Parser<I> for Elements {
307337
type Output = Vec<JsonValue>;
308-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
309-
let (output, next) = <Element as Parser<I>>::parse(input, current)?;
338+
fn parse(
339+
input: &I,
340+
current: I::Position,
341+
context: &ParserContext,
342+
) -> ResultOf<I, Self::Output> {
343+
let (output, next) = <Element as Parser<I>>::parse(input, current, context)?;
310344
let (rest, next) =
311-
<ZeroOrMore<Concat<CommaChar, Element>> as Parser<I>>::parse(input, next)?;
345+
<ZeroOrMore<Concat<CommaChar, Element>> as Parser<I>>::parse(input, next, context)?;
312346
let mut result = Vec::new();
313347
result.push(output);
314348
if let Either::A(rest) = rest {
@@ -322,12 +356,35 @@ pub struct Array;
322356

323357
impl<I: Input> Parser<I> for Array {
324358
type Output = Vec<JsonValue>;
325-
fn parse(input: &I, current: I::Position) -> ResultOf<I, Self::Output> {
326-
let (_, next) = <OpenSquareBracketChar as Parser<I>>::parse(input, current)?;
327-
let (res, next) = <Elements as Parser<I>>::parse(input, next)?;
328-
let (_, next) = <CloseSquareBracketChar as Parser<I>>::parse(input, next)?;
359+
fn parse(
360+
input: &I,
361+
current: I::Position,
362+
context: &ParserContext,
363+
) -> ResultOf<I, Self::Output> {
364+
let context = &context.nest(input, current)?;
365+
let (_, next) = <OpenSquareBracketChar as Parser<I>>::parse(input, current, context)?;
366+
let (res, next) = <Elements as Parser<I>>::parse(input, next, context)?;
367+
let (_, next) = <CloseSquareBracketChar as Parser<I>>::parse(input, next, context)?;
329368
Ok((res, next))
330369
}
331370
}
332371

333-
pub type Json = Element;
372+
pub struct Json;
373+
374+
impl<I: Input> Parser<I> for Json {
375+
type Output = <Element as Parser<I>>::Output;
376+
fn parse(
377+
input: &I,
378+
current: I::Position,
379+
context: &ParserContext,
380+
) -> ResultOf<I, Self::Output> {
381+
let (_, next) = <Whitespace as Parser<I>>::parse(input, current, context)?;
382+
let (res, next) = <Element as Parser<I>>::parse(input, next, context)?;
383+
let (_, next) = <Whitespace as Parser<I>>::parse(input, next, context)?;
384+
if input.is_end(next) {
385+
Ok((res, next))
386+
} else {
387+
Err(input.error_at(next, "Expect end of input"))
388+
}
389+
}
390+
}

src/lib.rs

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
#![cfg_attr(not(feature = "std"), no_std)]
22

3-
use crate::impls::SimpleError;
4-
use crate::json::{Json, JsonValue};
5-
use crate::parser::Parser;
3+
pub use crate::impls::SimpleError;
4+
pub use crate::json::{Json, JsonValue};
5+
pub use crate::parser::{Parser, ParserContext, ParserOptions};
66

77
pub mod impls;
88
pub mod json;
99
pub mod parser;
1010

1111
pub fn parse_json(input: &str) -> Result<JsonValue, SimpleError> {
12-
Json::parse(&input, Default::default()).map(|(ret, _)| ret)
12+
parse_json_with_options(input, Default::default())
13+
}
14+
15+
pub fn parse_json_with_options(
16+
input: &str,
17+
options: ParserOptions,
18+
) -> Result<JsonValue, SimpleError> {
19+
Json::parse(&input, Default::default(), &ParserContext::new(options)).map(|(ret, _)| ret)
1320
}
1421

1522
#[cfg(test)]
1623
mod tests {
1724
use super::*;
25+
use crate::impls::SimplePosition;
1826
use crate::json::NumberValue;
1927

2028
#[test]
@@ -55,4 +63,83 @@ mod tests {
5563
]))
5664
)
5765
}
66+
67+
#[test]
68+
fn it_should_consume_all() {
69+
assert_eq!(
70+
parse_json(&r#""1"a"#),
71+
Err(SimpleError {
72+
reasons: vec![(
73+
SimplePosition {
74+
index: 3,
75+
line: 0,
76+
column: 3
77+
},
78+
"Expect end of input"
79+
)]
80+
})
81+
)
82+
}
83+
84+
#[test]
85+
fn it_accepts_nest_level() {
86+
assert_eq!(
87+
parse_json_with_options(
88+
&r#"{ "test": 1 }"#,
89+
ParserOptions {
90+
max_nest_level: Some(1)
91+
}
92+
),
93+
Ok(JsonValue::Object(vec![(
94+
vec!['t', 'e', 's', 't'],
95+
JsonValue::Number(NumberValue {
96+
integer: 1,
97+
fraction: 0,
98+
fraction_length: 0,
99+
exponent: 0
100+
})
101+
),]))
102+
);
103+
}
104+
105+
#[test]
106+
fn it_accepts_more_nest_level() {
107+
assert_eq!(
108+
parse_json_with_options(
109+
&r#"{ "test": { "a": [ {} ] } }"#,
110+
ParserOptions {
111+
max_nest_level: Some(5)
112+
}
113+
),
114+
Ok(JsonValue::Object(vec![(
115+
vec!['t', 'e', 's', 't'],
116+
JsonValue::Object(vec![(
117+
vec!['a'],
118+
JsonValue::Array(vec![JsonValue::Object(vec![])])
119+
)])
120+
)]))
121+
);
122+
}
123+
124+
#[test]
125+
fn it_error_on_too_deep_nest() {
126+
assert_eq!(
127+
parse_json_with_options(
128+
&r#"{ "test": { "a": [ {} ] } }"#,
129+
ParserOptions {
130+
max_nest_level: Some(3)
131+
}
132+
),
133+
Err(SimpleError {
134+
reasons: vec![(
135+
SimplePosition {
136+
index: 0,
137+
line: 0,
138+
column: 0
139+
},
140+
"Value"
141+
)]
142+
})
143+
);
144+
}
58145
}

0 commit comments

Comments
 (0)