From 45e888291c45259b562b2bcbce3458ca641e42a8 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Mon, 10 Feb 2020 14:59:28 -0500 Subject: [PATCH] Closer to parsing the json string --- src/lib.rs | 77 +++++++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e5391f0..840cca9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -254,42 +254,25 @@ impl JSON { let max = self.chars.len() - 1; let mut n = start; + // Minus sign if self.chars[n] == '-' && n < max { n += 1; } - if self.chars[n] == '0' && n < max { + // Integer Part + while self.chars[n].is_ascii_digit() && n < max { 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 { n += 1; - loop { - if n + 1 > max { - break; - } - - if self.chars[n + 1].is_ascii_digit() { - n += 1; - } else { - break; - } + while self.chars[n].is_ascii_digit() && n < max { + n += 1; } } + // Scientific notation part if self.chars[n] == 'e' || self.chars[n] == 'E' && n < max { n += 1; @@ -297,33 +280,30 @@ impl JSON { n += 1; } // expect digit - loop { - if n + 1 > max { - break; - } - - if self.chars[n + 1].is_ascii_digit() { - n += 1; - } else { - break; - } + while self.chars[n].is_ascii_digit() && n < max { + n += 1; } } // If there are numeric digits attempt to parse the digits as a number if n > start { - let end = if n < self.chars.len() { + let mut end = if n < self.chars.len() { n } else { 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]); match str.parse::() { - Ok(n) => { - self.increment(str.len() - 1); - return Ok(Some(JSONValue::Number(n))) + Ok(number) => { + self.increment(str.len()); + return Ok(Some(JSONValue::Number(number))) }, Err(e) => Err(ParseError::ExpectedDigit(format!("'{}', {:#?}", str, e))), } @@ -373,11 +353,17 @@ impl JSON { return Err(ParseError::ExpectedToken(msg)); } - self.increment(1); + self.skip(); 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) { let current = self.i; 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 = HashMap::new(); + hash_map.insert(String::from("foo"), JSONValue::String(String::from("bar"))); + assert_eq!(result, Ok(Some(JSONValue::Object(hash_map)))); + } + #[test] fn parse_json_types() { // Boolean / Null @@ -486,6 +481,10 @@ mod tests { // String let res = JSON::parse(r#""/^$/""#); 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]