From 0993780c897608f58fe2db286d77022cc2810b33 Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Fri, 7 Feb 2020 22:55:09 -0500 Subject: [PATCH] String parsing --- src/lib.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5569467..f498b55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ #![forbid(unsafe_code)] use std::collections::HashMap; use std::iter::FromIterator; +use std::{char, u16}; /// The type of JSON value #[derive(Debug, PartialEq)] @@ -194,17 +195,56 @@ impl JSON { let mut result = String::new(); while self.chars[self.i] != '"' { + // All the escape sequences... if self.chars[self.i] == '\\' { - todo!(); + let ch = self.chars[self.i + 1]; + if ['"', '\\', '/'].contains(&ch) { + let escaped = ch.escape_default().next().unwrap_or(ch); + + result.push(escaped); + self.i += 1; + } else if ['b', 'f', 'n', 'r', 't'].contains(&ch) { + let ch = match ch { + 'b' => '\u{8}', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => panic!("Shouldn't be possible!"), + }; + result.push(ch); + self.i += 1; + } else if ch == 'u' + && self.chars[self.i + 2].is_ascii_hexdigit() + && self.chars[self.i + 3].is_ascii_hexdigit() + && self.chars[self.i + 4].is_ascii_hexdigit() + && self.chars[self.i + 5].is_ascii_hexdigit() + { + // Blech, parse out a JSON unicode (utf16) escape code. Handles surrogate pairs + // by giving you the replacement character...because...yeah + let char_str = String::from_iter(&self.chars[self.i + 2..=self.i + 5]); + let code = u16::from_str_radix(&char_str, 16) + .expect("Failed to parse unicode escape number"); + let string = String::from_utf16_lossy(&[code]); + + result.push_str(&string); + + self.i += 5; + } + } else { + result.push(self.chars[self.i]); } + self.i += 1; } - Ok(None) + self.i += 1; + + Ok(Some(JSONValue::String(result))) } /// See if there's a `JSONValue::Number` next in the JSON fn parse_number(&mut self) -> Result, ParseError> { - Ok(None) + todo!(); } /// See if there's a `JSONValue::True`, `JSONValue::False`, or a `JSONValue::Null` next in the JSON @@ -281,6 +321,17 @@ mod tests { assert_eq!('x', parser.chars[parser.i]); } + #[test] + fn parse_string() { + let mut parser = JSON::new(r#""\t""#); + let res = JSON::parse_string(&mut parser); + assert_eq!(res, Ok(Some(JSONValue::String(String::from("\t"))))); + + let mut parser = JSON::new(r#""\u203d""#); + let res = JSON::parse_string(&mut parser); + assert_eq!(res, Ok(Some(JSONValue::String(String::from("‽"))))); + } + #[test] fn parse_empty_array() { let mut parser = JSON::new("[]");