1use crate::error::Error;
2use crate::result::Result;
3use crate::tokenizer::Tokenizer;
4use crate::tokenizer::{PeekableIter, Token};
5use std::collections::HashMap;
6use std::str::FromStr;
7
8#[derive(Debug, PartialEq)]
9pub enum Json {
10 Null,
11 Bool(bool),
12 Number(f64),
13 String(String),
14 Array(Vec<Box<Json>>),
15 Object(HashMap<String, Box<Json>>),
16}
17
18impl FromStr for Json {
19 type Err = Error;
20 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
21 let mut token_stream: PeekableIter<Token> =
22 s.parse::<Tokenizer>()?.tokenize()?.into_iter().peekable();
23 parse_item(&mut token_stream)
24 }
25}
26
27fn skip_token(token_stream: &mut PeekableIter<Token>, token: Token) -> Result<()> {
28 match token_stream.next() {
29 Some(ref tkn) if *tkn == token => Ok(()),
30 _ => Err(Error::Parse("token expected".into())),
31 }
32}
33
34fn parse_array(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
35 skip_token(token_stream, Token::SquareOpen)?;
36 let mut v = vec![];
37 loop {
38 match token_stream.peek() {
39 Some(Token::SquareClose) => break,
40 Some(_) => {
41 v.push(Box::new(parse_item(token_stream)?));
42 if let Some(Token::SquareClose) = token_stream.peek() {
43 continue;
44 }
45 skip_token(token_stream, Token::Coma)?;
46 }
47 _ => return Err(Error::Parse("unterminated array".into())),
48 }
49 }
50 skip_token(token_stream, Token::SquareClose)?;
51 Ok(Json::Array(v))
52}
53
54fn parse_object(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
55 skip_token(token_stream, Token::CurlyOpen)?;
56 let mut obj: HashMap<String, Box<Json>> = HashMap::default();
57 loop {
58 match token_stream.peek() {
59 Some(Token::CurlyClose) => break,
60 Some(_) => {
61 if let Json::String(key) = parse_string(token_stream)? {
62 skip_token(token_stream, Token::Colon)?;
63 let val = parse_item(token_stream)?;
64 obj.insert(key, Box::new(val));
65 if let Some(Token::CurlyClose) = token_stream.peek() {
66 continue;
67 }
68 skip_token(token_stream, Token::Coma)?;
69 } else {
70 return Err(Error::Parse("object key expected".into()));
71 }
72 }
73 _ => return Err(Error::Parse("unterminated object".into())),
74 }
75 }
76 skip_token(token_stream, Token::CurlyClose)?;
77 return Ok(Json::Object(obj));
78}
79
80pub fn parse_item(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
81 match token_stream.peek() {
82 Some(Token::NullValue) => parse_null(token_stream),
83 Some(Token::BoolValue(_)) => parse_bool(token_stream),
84 Some(Token::NumberValue(_)) => parse_number(token_stream),
85 Some(Token::StringValue(_)) => parse_string(token_stream),
86 Some(Token::SquareOpen) => parse_array(token_stream),
87 Some(Token::CurlyOpen) => parse_object(token_stream),
88 _ => Err(Error::Parse("unexpected token".into())),
89 }
90}
91
92pub fn parse_null(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
93 match token_stream.next() {
94 Some(Token::NullValue) => Ok(Json::Null),
95 _ => Err(Error::Parse("null expected".into())),
96 }
97}
98
99pub fn parse_bool(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
100 match token_stream.next() {
101 Some(Token::BoolValue(b)) => Ok(Json::Bool(b)),
102 _ => Err(Error::Parse("bool expected".into())),
103 }
104}
105
106pub fn parse_number(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
107 match token_stream.next() {
108 Some(Token::NumberValue(n)) => Ok(Json::Number(n)),
109 _ => Err(Error::Parse("number expected".into())),
110 }
111}
112
113pub fn parse_string(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
114 match token_stream.next() {
115 Some(Token::StringValue(s)) => Ok(Json::String(s)),
116 _ => Err(Error::Parse("string expected".into())),
117 }
118}