1#[cfg(not(feature = "std"))]
2extern crate alloc;
3
4#[cfg(not(feature = "std"))]
5use alloc::vec::Vec;
6
7use crate::json::{JsonObject, JsonValue, NumberValue};
8use lite_parser::{
9 impls::SimpleError,
10 literals,
11 parser::{
12 Concat, Concat3, Either, OneOf, OneOrMore, Parser, ParserContext, ParserOptions,
13 ZeroOrMore, ZeroOrOne,
14 },
15 parsers,
16 traits::{Error, Input, ResultOf},
17};
18
19use core::convert::TryInto;
20
21literals! {
22 pub WhitespaceChar => '\u{0020}' | '\u{000D}' | '\u{000A}' | '\u{0009}';
23 pub SignChar => '+' | '-';
24 pub NegativeSignChar => '-';
25 pub EChar => 'E' | 'e';
26 pub OneToNineChar => '1' ..= '9';
27 pub DigitChar => '0' ..= '9';
28 pub DotChar => '.';
29 pub HexChar => '0' ..= '9' | 'a' ..= 'f' | 'A' ..= 'F';
30 pub DoubleQuoteChar => '"';
31 pub OpenCurlyBracketChar => '{';
32 pub CloseCurlyBracketChar => '}';
33 pub CommaChar => ',';
34 pub OpenSquareBracketChar => '[';
35 pub CloseSquareBracketChar => ']';
36}
37
38pub type Whitespace = ZeroOrMore<WhitespaceChar>;
39
40pub type Sign = ZeroOrOne<SignChar>;
41
42pub type Digits = OneOrMore<DigitChar>;
43
44parsers! {
45 pub PositiveInteger = OneOf<Concat<OneToNineChar, Digits>, DigitChar>, u64, (output) => {
46 match output {
47 Either::A((c, cs)) => {
48 let mut val = c.to_digit(10).unwrap() as u64;
49 for c in cs {
50 val *= 10;
51 val += c.to_digit(10).unwrap() as u64;
52 }
53 val
54 },
55 Either::B(c) => c.to_digit(10).unwrap() as u64,
56 }
57 };
58
59 pub NegativeInteger = Concat<NegativeSignChar, PositiveInteger>, u64, (output) => {
60 let (_, output) = output;
61 output
62 };
63
64 pub Integer = OneOf<PositiveInteger, NegativeInteger>, (bool, u64), (output) => {
65 match output {
66 Either::A(a) => (false, a),
67 Either::B(b) => (true, b),
68 }
69 };
70
71 pub Fraction = ZeroOrOne<Concat<DotChar, Digits>>, (u64, u32), (output) => {
72 match output {
73 Either::A((_, cs)) => {
74 let mut val = 0u64;
75 let len = cs.len();
76 for c in cs {
77 val *= 10u64;
78 val += c.to_digit(10).unwrap() as u64;
79 }
80 (val, len as u32)
81 },
82 Either::B(_) => (0u64, 0u32),
83 }
84 };
85
86 pub Exponent = ZeroOrOne<Concat3<EChar, Sign, Digits>>, i32, (output) => {
87 match output {
88 Either::A((_, (s, cs))) => {
89 let mul = if let Either::A('-') = s { -1 } else { 1 };
90 let mut val = 0i32;
91 for c in cs {
92 val *= 10;
93 val += c.to_digit(10).unwrap() as i32;
94 }
95 val * mul
96 },
97 Either::B(_) => 0,
98 }
99 };
100
101 pub Number = Concat3<Integer, Fraction, Exponent>, NumberValue, (output) => {
102 let ((s, n), (f, e)) = output;
103 NumberValue {
104 integer: n,
105 fraction: f.0,
106 fraction_length: f.1,
107 exponent: e,
108 negative: s,
109 }
110 };
111
112 pub Hex = HexChar, u8, (output) => {
113 output.to_digit(16).unwrap() as u8
114 };
115
116 pub String = Concat3<DoubleQuoteChar, Characters, DoubleQuoteChar>, Vec<char>, (output) => {
117 match (output.1).0 {
118 Either::A(bytes) => bytes,
119 Either::B(_) => Vec::new(),
120 }
121 };
122}
123
124pub struct Escape;
125
126impl<I: Input> Parser<I> for Escape {
127 type Output = char;
128 fn parse(
129 input: &I,
130 current: I::Position,
131 context: &ParserContext,
132 ) -> ResultOf<I, Self::Output> {
133 let (c, next) = input
134 .next(current)
135 .map_err(|e| e.add_reason(current, "Escape"))?;
136 match c {
137 '"' | '\\' | '/' | 'b' | 'f' | 'n' | 'r' | 't' => Ok((c, next)),
138 'u' => {
139 let (b1, next) = <Hex as Parser<I>>::parse(input, next, context)?;
140 let (b2, next) = <Hex as Parser<I>>::parse(input, next, context)?;
141 let (b3, next) = <Hex as Parser<I>>::parse(input, next, context)?;
142 let (b4, next) = <Hex as Parser<I>>::parse(input, next, context)?;
143 let byte = (b1 as u32) << 24 | (b2 as u32) << 16 | (b3 as u32) << 8 | (b4 as u32);
144 let c = byte
145 .try_into()
146 .map_err(|_| input.error_at(current, "Escape"))?;
147 Ok((c, next))
148 }
149 _ => Err(input.error_at(current, "Escape")),
150 }
151 }
152}
153
154pub struct Character;
155
156impl<I: Input> Parser<I> for Character {
157 type Output = char;
158 fn parse(
159 input: &I,
160 current: I::Position,
161 context: &ParserContext,
162 ) -> ResultOf<I, Self::Output> {
163 let (c, next) = input
164 .next(current)
165 .map_err(|e| e.add_reason(current, "Character"))?;
166 match c {
167 '\\' => <Escape as Parser<I>>::parse(input, next, context),
168 '"' => Err(input.error_at(current, "Character")),
169 _ => Ok((c, next)),
170 }
171 }
172}
173
174pub type Characters = ZeroOrMore<Character>;
175
176pub struct Member;
177
178impl<I: Input> Parser<I> for Member {
179 type Output = (Vec<char>, JsonValue);
180 fn parse(
181 input: &I,
182 current: I::Position,
183 context: &ParserContext,
184 ) -> ResultOf<I, Self::Output> {
185 let (_, next) = <Whitespace as Parser<I>>::parse(input, current, context)?;
186 let (key, next) = <String as Parser<I>>::parse(input, next, context)?;
187 let (_, next) = <Whitespace as Parser<I>>::parse(input, next, context)?;
188 let next = input
189 .next(next)
190 .and_then(|(c, next)| {
191 if c == ':' {
192 Ok(next)
193 } else {
194 Err(input.error_at(next, "Character"))
195 }
196 })
197 .map_err(|e| e.add_reason(current, "Member"))?;
198 let (value, next) = <Element as Parser<I>>::parse(input, next, context)?;
199 Ok(((key, value), next))
200 }
201}
202
203pub struct Element;
204
205impl<I: Input> Parser<I> for Element {
206 type Output = JsonValue;
207 fn parse(
208 input: &I,
209 current: I::Position,
210 context: &ParserContext,
211 ) -> ResultOf<I, Self::Output> {
212 let (_, next) = <Whitespace as Parser<I>>::parse(input, current, context)?;
213 let (output, next) = <Value as Parser<I>>::parse(input, next, context)?;
214 let (_, next) = <Whitespace as Parser<I>>::parse(input, next, context)?;
215 Ok((output, next))
216 }
217}
218
219pub struct Value;
220
221impl<I: Input> Parser<I> for Value
222where
223 I::Position: Copy,
224{
225 type Output = JsonValue;
226 fn parse(
227 input: &I,
228 current: I::Position,
229 context: &ParserContext,
230 ) -> ResultOf<I, Self::Output> {
231 if let Ok((output, next)) = <Object as Parser<I>>::parse(input, current, context) {
232 return Ok((JsonValue::Object(output), next));
233 }
234 if let Ok((output, next)) = <Array as Parser<I>>::parse(input, current, context) {
235 return Ok((JsonValue::Array(output), next));
236 }
237 if let Ok((output, next)) = <String as Parser<I>>::parse(input, current, context) {
238 return Ok((JsonValue::String(output), next));
239 }
240 if let Ok((output, next)) = <Number as Parser<I>>::parse(input, current, context) {
241 return Ok((JsonValue::Number(output), next));
242 }
243 let (value, next) = input.next_range(current, 4)?;
244 if value == "null" {
245 return Ok((JsonValue::Null, next));
246 }
247 if value == "true" {
248 return Ok((JsonValue::Boolean(true), next));
249 }
250 let (value, next) = input.next_range(current, 5)?;
251 if value == "false" {
252 return Ok((JsonValue::Boolean(false), next));
253 }
254 Err(input.error_at(current, "Value"))
255 }
256}
257
258pub struct Object;
259
260impl<I: Input> Parser<I> for Object {
261 type Output = JsonObject;
262 fn parse(
263 input: &I,
264 current: I::Position,
265 context: &ParserContext,
266 ) -> ResultOf<I, Self::Output> {
267 let context = &context.nest(input, current)?;
268 let (_, next) = <OpenCurlyBracketChar as Parser<I>>::parse(input, current, context)?;
269 let (output, next) =
270 <OneOf<Members, Whitespace> as Parser<I>>::parse(input, next, context)?;
271 let (_, next) = <CloseCurlyBracketChar as Parser<I>>::parse(input, next, context)?;
272 let output = match output {
273 Either::A(a) => a,
274 Either::B(_) => Vec::new(),
275 };
276 Ok((output, next))
277 }
278}
279
280pub struct Members;
281
282impl<I: Input> Parser<I> for Members {
283 type Output = Vec<(Vec<char>, JsonValue)>;
284 fn parse(
285 input: &I,
286 current: I::Position,
287 context: &ParserContext,
288 ) -> ResultOf<I, Self::Output> {
289 let (output, next) = <Member as Parser<I>>::parse(input, current, context)?;
290 let (rest, next) =
291 <ZeroOrMore<Concat<CommaChar, Member>> as Parser<I>>::parse(input, next, context)?;
292 let mut result = Vec::new();
293 result.push(output);
294 if let Either::A(rest) = rest {
295 result.extend(rest.into_iter().map(|(_, m)| m))
296 }
297 Ok((result, next))
298 }
299}
300
301pub struct Elements;
302
303impl<I: Input> Parser<I> for Elements {
304 type Output = Vec<JsonValue>;
305 fn parse(
306 input: &I,
307 current: I::Position,
308 context: &ParserContext,
309 ) -> ResultOf<I, Self::Output> {
310 let (output, next) = <Element as Parser<I>>::parse(input, current, context)?;
311 let (rest, next) =
312 <ZeroOrMore<Concat<CommaChar, Element>> as Parser<I>>::parse(input, next, context)?;
313 let mut result = Vec::new();
314 result.push(output);
315 if let Either::A(rest) = rest {
316 result.extend(rest.into_iter().map(|(_, m)| m))
317 }
318 Ok((result, next))
319 }
320}
321
322pub struct Array;
323
324impl<I: Input> Parser<I> for Array {
325 type Output = Vec<JsonValue>;
326 fn parse(
327 input: &I,
328 current: I::Position,
329 context: &ParserContext,
330 ) -> ResultOf<I, Self::Output> {
331 let context = &context.nest(input, current)?;
332 let (_, next) = <OpenSquareBracketChar as Parser<I>>::parse(input, current, context)?;
333 let (output, next) =
334 <OneOf<Elements, Whitespace> as Parser<I>>::parse(input, next, context)?;
335 let (_, next) = <CloseSquareBracketChar as Parser<I>>::parse(input, next, context)?;
336 let output = match output {
337 Either::A(a) => a,
338 Either::B(_) => Vec::new(),
339 };
340 Ok((output, next))
341 }
342}
343
344pub struct Json;
345
346impl<I: Input> Parser<I> for Json {
347 type Output = <Element as Parser<I>>::Output;
348 fn parse(
349 input: &I,
350 current: I::Position,
351 context: &ParserContext,
352 ) -> ResultOf<I, Self::Output> {
353 let (_, next) = <Whitespace as Parser<I>>::parse(input, current, context)?;
354 let (res, next) = <Element as Parser<I>>::parse(input, next, context)?;
355 let (_, next) = <Whitespace as Parser<I>>::parse(input, next, context)?;
356 if input.is_end(next) {
357 Ok((res, next))
358 } else {
359 Err(input.error_at(next, "Expect end of input"))
360 }
361 }
362}
363
364pub fn parse_json(input: &str) -> Result<JsonValue, SimpleError> {
365 parse_json_with_options(input, Default::default())
366}
367
368pub fn parse_json_with_options(
369 input: &str,
370 options: ParserOptions,
371) -> Result<JsonValue, SimpleError> {
372 Json::parse(&input, Default::default(), &ParserContext::new(options)).map(|(ret, _)| ret)
373}
374
375#[cfg(test)]
376mod tests {
377 use super::*;
378 use crate::NumberValue;
379 use lite_parser::impls::SimplePosition;
380
381 #[test]
382 fn it_works() {
383 assert_eq!(
384 parse_json(
385 &r#"{ "test": 1, "test2": [1e-4, 2.041e2, true, false, null, "\"1\n\""], "test3": [], "test4": {} }"#
386 ),
387 Ok(JsonValue::Object(vec![
388 (
389 vec!['t', 'e', 's', 't'],
390 JsonValue::Number(NumberValue {
391 integer: 1,
392 fraction: 0,
393 fraction_length: 0,
394 exponent: 0,
395 negative: false,
396 })
397 ),
398 (
399 vec!['t', 'e', 's', 't', '2'],
400 JsonValue::Array(vec![
401 JsonValue::Number(NumberValue {
402 integer: 1,
403 fraction: 0,
404 fraction_length: 0,
405 exponent: -4,
406 negative: false,
407 }),
408 JsonValue::Number(NumberValue {
409 integer: 2,
410 fraction: 41,
411 fraction_length: 3,
412 exponent: 2,
413 negative: false,
414 }),
415 JsonValue::Boolean(true),
416 JsonValue::Boolean(false),
417 JsonValue::Null,
418 JsonValue::String(vec!['\"', '1', 'n', '\"'])
419 ])
420 ),
421 (vec!['t', 'e', 's', 't', '3'], JsonValue::Array(vec![])),
422 (vec!['t', 'e', 's', 't', '4'], JsonValue::Object(vec![]))
423 ]))
424 )
425 }
426
427 #[test]
428 fn it_should_consume_all() {
429 assert_eq!(
430 parse_json(&r#""1"a"#),
431 Err(SimpleError {
432 reasons: vec![(
433 SimplePosition {
434 index: 3,
435 line: 0,
436 column: 3
437 },
438 "Expect end of input"
439 )]
440 })
441 )
442 }
443
444 #[test]
445 fn it_accepts_nest_level() {
446 assert_eq!(
447 parse_json_with_options(
448 &r#"{ "test": 1 }"#,
449 ParserOptions {
450 max_nest_level: Some(1)
451 }
452 ),
453 Ok(JsonValue::Object(vec![(
454 vec!['t', 'e', 's', 't'],
455 JsonValue::Number(NumberValue {
456 integer: 1,
457 fraction: 0,
458 fraction_length: 0,
459 exponent: 0,
460 negative: false,
461 })
462 ),]))
463 );
464 }
465
466 #[test]
467 fn it_accepts_more_nest_level() {
468 assert_eq!(
469 parse_json_with_options(
470 &r#"{ "test": { "a": [ {} ] } }"#,
471 ParserOptions {
472 max_nest_level: Some(5)
473 }
474 ),
475 Ok(JsonValue::Object(vec![(
476 vec!['t', 'e', 's', 't'],
477 JsonValue::Object(vec![(
478 vec!['a'],
479 JsonValue::Array(vec![JsonValue::Object(vec![])])
480 )])
481 )]))
482 );
483 }
484
485 #[test]
486 fn it_error_on_too_deep_nest() {
487 assert_eq!(
488 parse_json_with_options(
489 &r#"{ "test": { "a": [ {} ] } }"#,
490 ParserOptions {
491 max_nest_level: Some(3)
492 }
493 ),
494 Err(SimpleError {
495 reasons: vec![(
496 SimplePosition {
497 index: 0,
498 line: 0,
499 column: 0
500 },
501 "Value"
502 )]
503 })
504 );
505 }
506
507 #[test]
508 fn handles_decimal_number() {
509 assert_eq!(
510 parse_json(&r#"-1.5"#,),
511 Ok(JsonValue::Number(NumberValue {
512 integer: 1,
513 fraction: 5,
514 fraction_length: 1,
515 exponent: 0,
516 negative: true,
517 }))
518 );
519
520 assert_eq!(
521 parse_json(&r#"-0.5"#,),
522 Ok(JsonValue::Number(NumberValue {
523 integer: 0,
524 fraction: 5,
525 fraction_length: 1,
526 exponent: 0,
527 negative: true,
528 }))
529 );
530
531 assert_eq!(
532 parse_json(&r#"0.5"#,),
533 Ok(JsonValue::Number(NumberValue {
534 integer: 0,
535 fraction: 5,
536 fraction_length: 1,
537 exponent: 0,
538 negative: false,
539 }))
540 );
541 }
542}