Closer to parsing the json string
This commit is contained in:
parent
d87c2cf165
commit
45e888291c
73
src/lib.rs
73
src/lib.rs
@ -254,42 +254,25 @@ impl JSON {
|
|||||||
let max = self.chars.len() - 1;
|
let max = self.chars.len() - 1;
|
||||||
let mut n = start;
|
let mut n = start;
|
||||||
|
|
||||||
|
// Minus sign
|
||||||
if self.chars[n] == '-' && n < max {
|
if self.chars[n] == '-' && n < max {
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.chars[n] == '0' && n < max {
|
// Integer Part
|
||||||
|
while self.chars[n].is_ascii_digit() && n < max {
|
||||||
n += 1;
|
n += 1;
|
||||||
} else if self.chars[n] >= '1' && self.chars[n] <= '9' && n < max {
|
|
||||||
n += 1;
|
|
||||||
loop {
|
|
||||||
if n + 1 > max {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.chars[n + 1].is_ascii_digit() {
|
|
||||||
n += 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decimal Part
|
||||||
if self.chars[n] == '.' && n < max {
|
if self.chars[n] == '.' && n < max {
|
||||||
n += 1;
|
n += 1;
|
||||||
loop {
|
while self.chars[n].is_ascii_digit() && n < max {
|
||||||
if n + 1 > max {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.chars[n + 1].is_ascii_digit() {
|
|
||||||
n += 1;
|
n += 1;
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scientific notation part
|
||||||
if self.chars[n] == 'e' || self.chars[n] == 'E' && n < max {
|
if self.chars[n] == 'e' || self.chars[n] == 'E' && n < max {
|
||||||
n += 1;
|
n += 1;
|
||||||
|
|
||||||
@ -297,33 +280,30 @@ impl JSON {
|
|||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
// expect digit
|
// expect digit
|
||||||
loop {
|
while self.chars[n].is_ascii_digit() && n < max {
|
||||||
if n + 1 > max {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.chars[n + 1].is_ascii_digit() {
|
|
||||||
n += 1;
|
n += 1;
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are numeric digits attempt to parse the digits as a number
|
// If there are numeric digits attempt to parse the digits as a number
|
||||||
if n > start {
|
if n > start {
|
||||||
let end = if n < self.chars.len() {
|
let mut end = if n < self.chars.len() {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
max
|
max
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hack to remove non-number characters
|
||||||
|
if !self.chars[end].is_ascii_digit() {
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
let str = String::from_iter(&self.chars[start..=end]);
|
let str = String::from_iter(&self.chars[start..=end]);
|
||||||
|
|
||||||
match str.parse::<f64>() {
|
match str.parse::<f64>() {
|
||||||
Ok(n) => {
|
Ok(number) => {
|
||||||
self.increment(str.len() - 1);
|
self.increment(str.len());
|
||||||
return Ok(Some(JSONValue::Number(n)))
|
return Ok(Some(JSONValue::Number(number)))
|
||||||
},
|
},
|
||||||
Err(e) => Err(ParseError::ExpectedDigit(format!("'{}', {:#?}", str, e))),
|
Err(e) => Err(ParseError::ExpectedDigit(format!("'{}', {:#?}", str, e))),
|
||||||
}
|
}
|
||||||
@ -373,11 +353,17 @@ impl JSON {
|
|||||||
return Err(ParseError::ExpectedToken(msg));
|
return Err(ParseError::ExpectedToken(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.increment(1);
|
self.skip();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Skip a character
|
||||||
|
fn skip(&mut self) {
|
||||||
|
self.increment(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Do a checked increment of the internal pointer index
|
||||||
fn increment(&mut self, amount: usize) {
|
fn increment(&mut self, amount: usize) {
|
||||||
let current = self.i;
|
let current = self.i;
|
||||||
if current + amount >= self.chars.len() {
|
if current + amount >= self.chars.len() {
|
||||||
@ -469,6 +455,15 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_object() {
|
||||||
|
let mut parser = JSON::new(r#"{"foo": "bar"}"#);
|
||||||
|
let result = JSON::parse_object(&mut parser);
|
||||||
|
let mut hash_map: HashMap<String, JSONValue> = HashMap::new();
|
||||||
|
hash_map.insert(String::from("foo"), JSONValue::String(String::from("bar")));
|
||||||
|
assert_eq!(result, Ok(Some(JSONValue::Object(hash_map))));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_json_types() {
|
fn parse_json_types() {
|
||||||
// Boolean / Null
|
// Boolean / Null
|
||||||
@ -486,6 +481,10 @@ mod tests {
|
|||||||
// String
|
// String
|
||||||
let res = JSON::parse(r#""/^$/""#);
|
let res = JSON::parse(r#""/^$/""#);
|
||||||
assert_eq!(res, Ok(JSONValue::String(String::from("/^$/"))), "Failed to parse string");
|
assert_eq!(res, Ok(JSONValue::String(String::from("/^$/"))), "Failed to parse string");
|
||||||
|
|
||||||
|
// Number array
|
||||||
|
let res = JSON::parse("[1, 2, 3]");
|
||||||
|
assert_eq!(res, Ok(JSONValue::Array(vec![JSONValue::Number(1f64), JSONValue::Number(2f64), JSONValue::Number(3f64)])));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user