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)]
|
#![forbid(unsafe_code)]
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
use std::{char, u16};
|
||||||
|
|
||||||
/// The type of JSON value
|
/// The type of JSON value
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -194,17 +195,56 @@ impl JSON {
|
|||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
|
|
||||||
while self.chars[self.i] != '"' {
|
while self.chars[self.i] != '"' {
|
||||||
|
// All the escape sequences...
|
||||||
if self.chars[self.i] == '\\' {
|
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
|
/// See if there's a `JSONValue::Number` next in the JSON
|
||||||
fn parse_number(&mut self) -> Result<Option<JSONValue>, ParseError> {
|
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
|
/// 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]);
|
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]
|
#[test]
|
||||||
fn parse_empty_array() {
|
fn parse_empty_array() {
|
||||||
let mut parser = JSON::new("[]");
|
let mut parser = JSON::new("[]");
|
||||||
|
Loading…
Reference in New Issue
Block a user