Mostly done, parse_number needs some more work
This commit is contained in:
parent
0993780c89
commit
b0c2eb7e08
92
src/lib.rs
92
src/lib.rs
@ -244,7 +244,62 @@ impl JSON {
|
||||
|
||||
/// See if there's a `JSONValue::Number` next in the JSON
|
||||
fn parse_number(&mut self) -> Result<Option<JSONValue>, ParseError> {
|
||||
todo!();
|
||||
self.skip_whitespace();
|
||||
|
||||
// All this looping basically just counts the number of characters in the number
|
||||
let start = self.i;
|
||||
let max = self.chars.len() - 1;
|
||||
let mut n = start;
|
||||
|
||||
if self.chars[n] == '-' && n < max {
|
||||
n += 1;
|
||||
}
|
||||
|
||||
if self.chars[n] == '0' && n < max {
|
||||
n += 1;
|
||||
} else if self.chars[n] >= '1' && self.chars[n] <= '9' && n < max {
|
||||
n += 1;
|
||||
while self.chars[n].is_ascii_digit() {
|
||||
// && n < max {
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if self.chars[n] == '.' && n < max {
|
||||
n += 1;
|
||||
while self.chars[n].is_ascii_digit() && n < max {
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if self.chars[n] == 'e' || self.chars[n] == 'E' && n < max {
|
||||
n += 1;
|
||||
|
||||
if self.chars[n] == '-' || self.chars[n] == '+' && n < max {
|
||||
n += 1;
|
||||
}
|
||||
|
||||
while self.chars[n].is_ascii_digit() && n < max {
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if n > start {
|
||||
let end = if n < self.chars.len() {
|
||||
n
|
||||
} else {
|
||||
self.chars.len()
|
||||
};
|
||||
|
||||
let str = String::from_iter(&self.chars[start..=end]);
|
||||
|
||||
match str.parse::<f64>() {
|
||||
Ok(n) => Ok(Some(JSONValue::Number(n))),
|
||||
Err(e) => Err(ParseError::ExpectedDigit(format!("{:#?}", (str, e)))),
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// See if there's a `JSONValue::True`, `JSONValue::False`, or a `JSONValue::Null` next in the JSON
|
||||
@ -284,7 +339,7 @@ impl JSON {
|
||||
/// error is returned
|
||||
fn eat(&mut self, ch: char) -> Result<(), ParseError> {
|
||||
if self.chars[self.i] != ch {
|
||||
let msg = format!(r#"Expected "{}"."#, ch);
|
||||
let msg = format!("Expected '{}'.", ch);
|
||||
return Err(ParseError::ExpectedToken(msg));
|
||||
}
|
||||
|
||||
@ -339,6 +394,17 @@ mod tests {
|
||||
assert_eq!(res, Ok(JSONValue::Array(vec![])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_number() {
|
||||
let mut parser = JSON::new("3.14159");
|
||||
let res = JSON::parse_number(&mut parser);
|
||||
assert_eq!(res, Ok(Some(JSONValue::Number(3.14159f64))));
|
||||
|
||||
let mut parser = JSON::new("3e4");
|
||||
let res = JSON::parse_number(&mut parser);
|
||||
assert_eq!(res, Ok(Some(JSONValue::Number(3e4f64))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_parse_array_of_keywords() {
|
||||
let result = JSON::parse("[true,false,null]");
|
||||
@ -352,4 +418,26 @@ mod tests {
|
||||
]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_parse_arbitrary_json() {
|
||||
let result = JSON::parse(
|
||||
r#"[{
|
||||
"a": 9.38083151965,
|
||||
"b": 4e3,
|
||||
"c": [1, 2, 3],
|
||||
"d": "foo",
|
||||
"e": {
|
||||
"f": {
|
||||
"g": {
|
||||
"h": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"i": ["\"", "\\", "/", "\b", "\f", "\n", "\r", "\t", "\u0001", "\uface"]
|
||||
}]"#,
|
||||
);
|
||||
// let msg = format!("{:#?}", result);
|
||||
assert!(result.is_ok(), format!("{:#?}", result));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user