#![recursion_limit = "1024"]
use std::fmt::Debug;
use aoc_parse::{parser, prelude::*};
#[track_caller]
fn assert_parse_eq
(parser: P, s: &str, expected: E)
where
P: Parser,
P::Output: PartialEq + Debug,
E: Debug,
{
match parser.parse(s) {
Err(err) => panic!("parse failed: {}", err),
Ok(val) => assert_eq!(val, expected),
}
}
#[test]
fn test_rule_set_json() {
use serde_json::{Map, Number, Value};
let json = parser!(
// https://www.rfc-editor.org/rfc/rfc8259#page-5
rule ws: () = { ' ', '\t', '\r', '\n' }* => ();
rule value: Value = {
"null" => Value::Null,
"false" => Value::Bool(false),
"true" => Value::Bool(true),
o:object => Value::Object(o),
a:array => Value::Array(a),
n:number => Value::Number(n),
s:json_string => Value::String(s),
};
rule json_string: String =
'"'
s:string(char_of( // approximation: any ascii character but " and backslash
" !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~"
)*)
'"'
=> s;
rule object: Map =
ws '{' ws
members:repeat_sep(member, ws ',' ws)
ws '}' ws
=> { eprintln!("NUMBER OF MEMBERS: {}", members.len()); members.into_iter().collect()};
rule member: (String, Value) =
k:json_string ws ':' ws v:value => (k, v);
rule array: Vec =
ws '[' ws
elems:repeat_sep(value, ws ',' ws)
ws ']' ws
=> elems;
rule number: Number =
s:string('-'? int frac? exp?) => s.parse::().unwrap();
rule int: () = {'0' => (), char_of("123456789") digit* => ()};
rule frac: () = '.' digit+ => ();
rule exp: () = {'e', 'E'} i64 => ();
value
);
// Example from the standard (section 13).
assert_parse_eq(
&json,
r#"
{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": 100
},
"Animated" : false,
"IDs": [116, 943, 234, 38793]
}
}
"#,
serde_json::json!(
{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": 100
},
"Animated" : false,
"IDs": [116, 943, 234, 38793]
}
}
),
);
assert_parse_eq(
&json,
r#" [
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},
{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]"#,
serde_json::json!([
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},
{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]),
);
}