use crate::{Read, Stack, Deserializer, JsonError};
mod unicode;
mod hex;
use unicode::*;
use hex::*;
pub(crate) struct ValidateString<'read, 'parent, R: Read<'read>, S: Stack> {
deserializer: &'parent mut Deserializer<'read, R, S>,
done: bool,
}
impl<'read, 'parent, R: Read<'read>, S: Stack> ValidateString<'read, 'parent, R, S> {
#[inline(always)]
fn next_char(&mut self) -> Result<Option<StringCharacter>, JsonError<'read, R, S>> {
if let Some(e) = self.deserializer.error {
return Err(e);
}
let this = self.deserializer.reader.read_byte().map_err(JsonError::ReadError)?;
Ok(match this {
b'\x20' ..= b'\x21' | b'\x23' ..= b'\x5b' | b'\x5d' ..= b'\x7f' => {
Some(StringCharacter::Character(this as char))
}
b'\x80' ..= b'\xff' => {
Some(StringCharacter::Character(read_non_ascii_utf8(&mut self.deserializer.reader, this)?))
}
b'\\' => {
let escaped = self.deserializer.reader.read_byte().map_err(JsonError::ReadError)?;
match escaped {
b'"' | b'\\' | b'/' => Some(StringCharacter::Character(escaped as char)),
b'b' => Some(StringCharacter::Character('\x08')),
b'f' => Some(StringCharacter::Character('\x0c')),
b'n' => Some(StringCharacter::Character('\n')),
b'r' => Some(StringCharacter::Character('\r')),
b't' => Some(StringCharacter::Character('\t')),
b'\x75' => {
let bytes = [
self.deserializer.reader.read_byte().map_err(JsonError::ReadError)?,
self.deserializer.reader.read_byte().map_err(JsonError::ReadError)?,
self.deserializer.reader.read_byte().map_err(JsonError::ReadError)?,
self.deserializer.reader.read_byte().map_err(JsonError::ReadError)?,
];
if !validate_hex(bytes) {
Err(JsonError::InvalidValue)?;
}
Some(StringCharacter::EscapedUnicode(bytes))
}
_ => Err(JsonError::InvalidValue)?,
}
}
b'"' => {
self.done = true;
None
}
_ => Err(JsonError::InvalidValue)?,
})
}
}
pub(crate) enum StringCharacter {
Character(char),
EscapedUnicode([u8; 4]),
}
impl<'read, 'parent, R: Read<'read>, S: Stack> Iterator for ValidateString<'read, 'parent, R, S> {
type Item = Result<StringCharacter, JsonError<'read, R, S>>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self.next_char() {
Ok(Some(res)) => Some(Ok(res)),
Ok(None) => None,
Err(e) => {
self.deserializer.error = Some(e);
self.done = true;
Some(Err(e))
}
}
}
}
pub(crate) struct String<'read, 'parent, R: Read<'read>, S: Stack> {
validation: ValidateString<'read, 'parent, R, S>,
errored: bool,
}
impl<'read, 'parent, R: Read<'read>, S: Stack> String<'read, 'parent, R, S> {
#[inline(always)]
pub(crate) fn read(deserializer: &'parent mut Deserializer<'read, R, S>) -> Self {
String { validation: ValidateString { deserializer, done: false }, errored: false }
}
#[inline(always)]
fn drop(&mut self) {
while !self.validation.done {
self.validation.next();
}
}
}
fn handle_escaped_unicode<'read, 'parent, R: Read<'read>, S: Stack>(
hex: [u8; 4],
validation: &mut ValidateString<'read, 'parent, R, S>,
) -> Result<char, JsonError<'read, R, S>> {
let next = read_hex(hex)?;
let next_is_utf16_high_surrogate = matches!(next, 0xd800 ..= 0xdbff);
let codepoint = if next_is_utf16_high_surrogate {
let high = (next - 0xd800) << 10;
let Some(Ok(StringCharacter::EscapedUnicode(hex))) = validation.next() else {
Err(JsonError::NotUtf8)?
};
let low = read_hex(hex)?;
let Some(low) = low.checked_sub(0xdc00) else { Err(JsonError::NotUtf8)? };
high + low + 0x10000
} else {
next
};
char::from_u32(codepoint).ok_or(JsonError::NotUtf8)
}
impl<'read, 'parent, R: Read<'read>, S: Stack> Iterator for String<'read, 'parent, R, S> {
type Item = Result<char, JsonError<'read, R, S>>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.errored | self.validation.done {
None?;
}
Some(match self.validation.next()? {
Ok(StringCharacter::Character(char)) => Ok(char),
Ok(StringCharacter::EscapedUnicode(hex)) => {
let res = handle_escaped_unicode(hex, &mut self.validation);
if res.is_err() {
self.errored = true;
}
res
}
Err(e) => Err(e),
})
}
}
pub(crate) struct StringKey<'read, 'parent, R: Read<'read>, S: Stack>(
pub(crate) Option<String<'read, 'parent, R, S>>,
);
impl<'read, 'parent, R: Read<'read>, S: Stack> StringKey<'read, 'parent, R, S> {
#[inline(always)]
pub(super) fn drop(&mut self) -> Option<&'parent mut Deserializer<'read, R, S>> {
let mut string = self.0.take()?;
string.drop();
let deserializer = string.validation.deserializer;
if deserializer.error.is_none() {
match crate::advance_past_colon(&mut deserializer.reader) {
Ok(()) => {}
Err(e) => deserializer.error = Some(e),
}
}
Some(deserializer)
}
}
impl<'read, 'parent, R: Read<'read>, S: Stack> Iterator for StringKey<'read, 'parent, R, S> {
type Item = Result<char, JsonError<'read, R, S>>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.0.as_mut().and_then(String::next)
}
}
pub(crate) struct StringValue<'read, 'parent, R: Read<'read>, S: Stack>(
pub(crate) String<'read, 'parent, R, S>,
);
impl<'read, 'parent, R: Read<'read>, S: Stack> Drop for StringValue<'read, 'parent, R, S> {
#[inline(always)]
fn drop(&mut self) {
let string = &mut self.0;
string.drop();
let deserializer = &mut string.validation.deserializer;
if deserializer.error.is_none() {
match crate::advance_past_comma_or_to_close(&mut deserializer.reader) {
Ok(()) => {}
Err(e) => deserializer.error = Some(e),
}
}
}
}
impl<'read, 'parent, R: Read<'read>, S: Stack> Iterator for StringValue<'read, 'parent, R, S> {
type Item = Result<char, JsonError<'read, R, S>>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}