#![cfg(feature = "alloc")] //#![feature(trace_macros)] #[macro_use] extern crate nom; use nom::{character::is_alphanumeric, number::complete::recognize_float}; use std::str; use std::collections::HashMap; #[derive(Debug, PartialEq)] pub enum JsonValue { Str(String), Num(f32), Array(Vec), Object(HashMap), } named!(float, flat_map!(recognize_float, parse_to!(f32))); //FIXME: verify how json strings are formatted named!( string<&str>, delimited!( char!('"'), //map_res!(escaped!(call!(alphanumeric), '\\', is_a!("\"n\\")), str::from_utf8), map_res!( escaped!(take_while1!(is_alphanumeric), '\\', one_of!("\"n\\")), str::from_utf8 ), char!('"') ) ); named!( array>, ws!(delimited!( char!('['), separated_list!(char!(','), value), char!(']') )) ); named!( key_value<(&str, JsonValue)>, ws!(separated_pair!(string, char!(':'), value)) ); named!( hash>, ws!(map!( delimited!(char!('{'), separated_list!(char!(','), key_value), char!('}')), |tuple_vec| { let mut h: HashMap = HashMap::new(); for (k, v) in tuple_vec { h.insert(String::from(k), v); } h } )) ); named!( value, ws!(alt!( hash => { |h| JsonValue::Object(h) } | array => { |v| JsonValue::Array(v) } | string => { |s| JsonValue::Str(String::from(s)) } | float => { |num| JsonValue::Num(num) } )) ); #[test] fn json_object() { let input = r#"{ "a": 42, "b": "x" }\0"#; let mut expected_map = HashMap::new(); expected_map.insert(String::from("a"), JsonValue::Num(42f32)); expected_map.insert(String::from("b"), JsonValue::Str(String::from("x"))); let expected = JsonValue::Object(expected_map); assert_eq!(expected, value(input.as_bytes()).unwrap().1); } #[test] fn json_array() { let input = r#"[ 42, "x" ]\0"#; let expected_vec = vec![ JsonValue::Num(42f32), JsonValue::Str(String::from("x")) ]; let expected = JsonValue::Array(expected_vec); assert_eq!(expected, value(input.as_bytes()).unwrap().1); }