String parsing
This commit is contained in:
parent
72c3eecf21
commit
0993780c89
57
src/lib.rs
57
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<Option<JSONValue>, 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("[]");
|
||||
|
Loading…
Reference in New Issue
Block a user