use core::fmt;
use core::marker::PhantomData;
use crate::error::{ErrorCode, PResult};
use crate::json::traits::{Read, ReadArray, ReadEnum, ReadInternallyTagged, ReadObject};
use crate::num::atof::{parse_float, scan_number};
use crate::num::atoi::{
out_of_range, parse_i64, parse_u128, parse_unsigned_u64, parse_unsigned_u128, reject_float_tail,
};
use crate::options::{Options, Standard};
use crate::swar::{escape_mask, find_byte, first_match, load_u64, needs_escape};
use crate::traits::{Fields, Keys, Variants, resolve_key, resolve_variant};
pub const MAX_DEPTH: u32 = 256;
pub struct Parser<'de, O: Options = Standard> {
data: &'de str,
bytes: &'de [u8],
idx: usize,
depth: u32,
error_key: Option<&'static str>,
deferred: Vec<Deferred>,
options: PhantomData<fn() -> O>,
}
#[derive(Clone, Copy)]
struct Deferred {
start: usize,
end: usize,
depth: u32,
}
impl<'de> Parser<'de> {
#[inline]
pub fn new(input: &'de str) -> Self {
Self::with_options(input)
}
}
impl<'de, O: Options> Parser<'de, O> {
#[inline]
pub fn with_options(input: &'de str) -> Self {
Parser {
data: input,
bytes: input.as_bytes(),
idx: 0,
depth: 0,
error_key: None,
deferred: Vec::new(),
options: PhantomData,
}
}
#[inline(always)]
pub fn position(&self) -> usize {
self.idx
}
#[inline(always)]
pub fn error_key(&self) -> Option<&'static str> {
self.error_key
}
#[inline(always)]
pub fn set_error_key(&mut self, key: &'static str) {
self.error_key = Some(key);
}
#[inline]
pub fn rewind(&mut self, to: usize) {
self.idx = to.min(self.idx);
self.error_key = None;
}
#[inline(always)]
pub fn rest(&self) -> &'de [u8] {
&self.bytes[self.idx..]
}
#[inline(always)]
pub fn rest_str(&self) -> &'de str {
&self.data[self.idx..]
}
#[inline(always)]
fn remaining(&self) -> usize {
self.bytes.len() - self.idx
}
#[inline(always)]
pub(crate) fn peek(&self) -> Option<u8> {
self.bytes.get(self.idx).copied()
}
#[inline(always)]
pub fn skip_ws(&mut self) {
self.idx = skip_ws_at::<O>(self.bytes, self.idx);
}
#[inline(always)]
pub fn try_byte(&mut self, b: u8) -> bool {
if self.idx < self.bytes.len() && self.bytes[self.idx] == b {
self.idx += 1;
true
} else {
false
}
}
#[inline(always)]
pub fn expect(&mut self, b: u8, code: ErrorCode) -> PResult<()> {
if self.idx < self.bytes.len() && self.bytes[self.idx] == b {
self.idx += 1;
Ok(())
} else if self.idx >= self.bytes.len() {
Err(ErrorCode::UnexpectedEnd)
} else {
Err(code)
}
}
#[inline(always)]
pub fn colon(&mut self) -> PResult<()> {
self.skip_ws();
self.expect(b':', ErrorCode::ExpectedColon)?;
self.skip_ws();
Ok(())
}
#[inline(always)]
pub(crate) fn comma_or_close(&mut self, close: u8) -> PResult<bool> {
self.skip_ws();
if self.try_byte(b',') {
self.skip_ws();
return Ok(true);
}
if self.try_byte(close) {
return Ok(false);
}
Err(if self.idx >= self.bytes.len() {
ErrorCode::UnexpectedEnd
} else {
ErrorCode::ExpectedComma
})
}
#[inline(always)]
pub(crate) fn enter(&mut self) -> PResult<()> {
if self.depth >= MAX_DEPTH {
return Err(ErrorCode::ExceededMaxDepth);
}
self.depth += 1;
Ok(())
}
#[inline(always)]
pub(crate) fn nested<R>(&mut self, body: impl FnOnce(&mut Self) -> PResult<R>) -> PResult<R> {
self.enter()?;
let result = body(self);
self.leave();
result
}
#[inline(always)]
pub(crate) fn leave(&mut self) {
debug_assert!(
self.depth > 0,
"structio: `leave` without a matching `enter`, which would disable the nesting limit"
);
self.depth -= 1;
}
#[inline(always)]
pub fn match_key(&mut self, key: &'static str) -> bool {
let k = key.as_bytes();
let n = k.len();
let i = self.idx;
if i + n < self.bytes.len() && self.bytes[i + n] == b'"' && &self.bytes[i..i + n] == k {
self.idx = i + n + 1;
true
} else {
false
}
}
pub fn read_object<T: ReadObject<'de>>(&mut self, value: &mut T) -> PResult<()> {
self.skip_ws();
let open = self.idx;
self.expect(b'{', ErrorCode::ExpectedBrace)?;
let seen = self.nested(|p| {
p.skip_ws();
if p.try_byte(b'}') {
return Ok(0);
}
p.object_members::<T>(value)
})?;
self.require_fields::<T>(seen, open)
}
pub fn read_object_rest<T: ReadObject<'de>>(
&mut self,
value: &mut T,
open: usize,
) -> PResult<()> {
let seen = self.rest_members::<T>(value);
self.leave();
self.require_fields::<T>(seen?, open)
}
#[inline(always)]
fn rest_members<T: ReadObject<'de>>(&mut self, value: &mut T) -> PResult<u64> {
let mut seen = if self.comma_or_close(b'}')? {
self.object_members::<T>(value)?
} else {
0
};
if let Some(run) = self.take_deferred() {
seen |= self.deferred_members::<T>(value, run)?;
}
Ok(seen)
}
pub fn finish_internally_tagged(&mut self) -> PResult<()> {
let result = self.unknown_members();
self.leave();
result
}
#[inline(always)]
fn unknown_members(&mut self) -> PResult<()> {
while self.comma_or_close(b'}')? {
self.expect(b'"', ErrorCode::ExpectedQuote)?;
if O::ERROR_ON_UNKNOWN_KEYS {
return self.unknown_key();
}
self.skip_unknown_member()?;
}
if let Some(run) = self.take_deferred() {
let resume = self.idx;
self.idx = run.start;
while self.idx != run.end {
self.expect(b'"', ErrorCode::ExpectedQuote)?;
if O::ERROR_ON_UNKNOWN_KEYS {
return self.unknown_key();
}
self.skip_unknown_member()?;
if !self.comma_or_close(b'}')? {
return Err(ErrorCode::ExpectedTag);
}
}
self.idx = resume;
}
Ok(())
}
#[inline]
fn unknown_key(&mut self) -> PResult<()> {
let key = self.idx;
self.skip_string_body()?;
self.idx = key;
Err(ErrorCode::UnknownKey)
}
#[inline]
fn object_members<T: ReadObject<'de>>(&mut self, value: &mut T) -> PResult<u64> {
let mut seen = 0u64;
loop {
self.object_member::<T>(value, &mut seen)?;
if !self.comma_or_close(b'}')? {
return Ok(seen);
}
}
}
#[inline]
fn object_member<T: ReadObject<'de>>(&mut self, value: &mut T, seen: &mut u64) -> PResult<()> {
let map = T::MAP;
let n = map.n as usize;
self.expect(b'"', ErrorCode::ExpectedQuote)?;
let mut index = map.lookup(T::KEYS, self.rest());
let matched = if index < n {
index = resolve_key::<T>(index);
T::read_field(value, index, self)?
} else {
false
};
if Fields::<O, T>::TRACK && matched {
*seen |= Fields::<O, T>::seen(index);
}
if !matched {
if O::ERROR_ON_UNKNOWN_KEYS {
return self.unknown_key();
}
self.skip_unknown_member()?;
}
Ok(())
}
fn deferred_members<T: ReadObject<'de>>(
&mut self,
value: &mut T,
run: Deferred,
) -> PResult<u64> {
let resume = self.idx;
self.idx = run.start;
let mut seen = 0u64;
while self.idx != run.end {
self.object_member::<T>(value, &mut seen)?;
if !self.comma_or_close(b'}')? {
return Err(ErrorCode::ExpectedTag);
}
}
self.idx = resume;
Ok(seen)
}
#[inline(always)]
fn take_deferred(&mut self) -> Option<Deferred> {
match self.deferred.last() {
Some(run) if run.depth == self.depth => self.deferred.pop(),
_ => None,
}
}
fn find_late_tag(&mut self, tag: &'static str, first: usize) -> PResult<()> {
let mut at = first;
loop {
self.idx = at;
self.expect(b'"', ErrorCode::ExpectedQuote)?;
if self.match_key(tag) {
self.deferred.push(Deferred {
start: first,
end: at,
depth: self.depth,
});
return Ok(());
}
self.skip_unknown_member()?;
if !self.comma_or_close(b'}')? {
self.idx = first;
return Err(ErrorCode::ExpectedTag);
}
at = self.idx;
}
}
#[inline]
fn require_fields<T: Keys>(&mut self, seen: u64, open: usize) -> PResult<()> {
let mask = Fields::<O, T>::MASK;
if seen & mask != mask {
self.idx = open;
self.error_key = Fields::<O, T>::missing(seen);
return Err(ErrorCode::MissingKey);
}
Ok(())
}
fn skip_unknown_member(&mut self) -> PResult<()> {
self.skip_string_body()?;
self.colon()?;
self.skip_value()
}
pub fn read_enum<T: ReadEnum<'de>>(&mut self, value: &mut T) -> PResult<()> {
self.skip_ws();
match self.peek() {
Some(b'"') => {
self.idx += 1;
self.dispatch_variant(value, T::read_name)
}
Some(b'{') => {
let open = self.idx;
self.idx += 1;
self.nested(|p| {
p.skip_ws();
if p.peek() == Some(b'}') {
p.idx = open;
return Err(ErrorCode::ExpectedVariant);
}
p.expect(b'"', ErrorCode::ExpectedQuote)?;
p.dispatch_variant(value, T::read_payload)?;
if p.comma_or_close(b'}')? {
p.idx = open;
return Err(ErrorCode::ExpectedVariant);
}
Ok(())
})
}
Some(_) => Err(ErrorCode::ExpectedVariant),
None => Err(ErrorCode::UnexpectedEnd),
}
}
#[inline]
fn dispatch_variant<T, F>(&mut self, value: &mut T, take: F) -> PResult<()>
where
T: Variants,
F: FnOnce(&mut T, usize, &mut Self) -> PResult<bool>,
{
let map = T::MAP;
let at = self.idx;
let index = map.lookup(T::VARIANTS, self.rest());
if index < map.n as usize && take(value, resolve_variant::<T>(index), self)? {
return Ok(());
}
self.idx = at;
self.skip_string_body()?;
self.idx = at;
Err(ErrorCode::UnknownVariant)
}
pub fn read_internally_tagged<T: ReadInternallyTagged<'de>>(
&mut self,
value: &mut T,
) -> PResult<()> {
self.skip_ws();
let open = self.idx;
self.expect(b'{', ErrorCode::ExpectedBrace)?;
let depth = self.depth;
let runs = self.deferred.len();
let result = self.tagged_object::<T>(value, open);
if result.is_err() {
self.depth = depth;
self.deferred.truncate(runs);
}
result
}
#[inline(always)]
fn tagged_object<T: ReadInternallyTagged<'de>>(
&mut self,
value: &mut T,
open: usize,
) -> PResult<()> {
self.enter()?;
self.skip_ws();
if self.peek() == Some(b'}') {
self.idx = open;
return Err(ErrorCode::ExpectedTag);
}
let first = self.idx;
self.expect(b'"', ErrorCode::ExpectedQuote)?;
if !self.match_key(T::TAG) {
self.find_late_tag(T::TAG, first)?;
}
self.colon()?;
match self.peek() {
Some(b'"') => self.idx += 1,
Some(_) => {
self.idx = first;
return Err(ErrorCode::ExpectedTag);
}
None => return Err(ErrorCode::UnexpectedEnd),
}
self.dispatch_variant(value, |v, i, p| T::read_variant(v, i, p, open))
}
#[inline]
pub fn read_array<T: ReadArray<'de>>(&mut self, value: &mut T) -> PResult<()> {
let count = self.read_seq(|p, i| value.read_element(i, p))?;
if count != T::LEN {
return Err(ErrorCode::ArrayLengthMismatch);
}
Ok(())
}
#[inline]
pub fn read_seq<F>(&mut self, mut element: F) -> PResult<usize>
where
F: FnMut(&mut Self, usize) -> PResult<()>,
{
self.skip_ws();
self.expect(b'[', ErrorCode::ExpectedBracket)?;
self.nested(|p| {
p.skip_ws();
if p.try_byte(b']') {
return Ok(0);
}
let mut count = 0usize;
loop {
element(p, count)?;
count += 1;
if !p.comma_or_close(b']')? {
return Ok(count);
}
}
})
}
#[inline]
pub fn read_map<F>(&mut self, mut entry: F) -> PResult<()>
where
F: FnMut(&mut Self, JsonStr<'de>) -> PResult<()>,
{
self.read_map_located(|p, key, _| entry(p, key))
}
#[inline]
pub fn read_map_located<F>(&mut self, mut entry: F) -> PResult<()>
where
F: FnMut(&mut Self, JsonStr<'de>, usize) -> PResult<()>,
{
self.skip_ws();
self.expect(b'{', ErrorCode::ExpectedBrace)?;
self.nested(|p| {
p.skip_ws();
if p.try_byte(b'}') {
return Ok(());
}
loop {
p.expect(b'"', ErrorCode::ExpectedQuote)?;
let at = p.idx;
let key = p.read_string_body()?;
p.colon()?;
entry(p, key, at)?;
if !p.comma_or_close(b'}')? {
return Ok(());
}
}
})
}
#[inline(always)]
pub fn read_bool(&mut self) -> PResult<bool> {
use core::hint::select_unpredictable as select;
const TRUE: u64 = u64::from_le_bytes(*b"true\0\0\0\0");
const FALSE: u64 = u64::from_le_bytes(*b"false\0\0\0");
let i = self.idx;
if i + 8 <= self.bytes.len() {
let word = unsafe { load_u64(self.bytes, i) };
let is_f = word as u8 == b'f';
let want = select(is_f, FALSE, TRUE);
let mask = select(is_f, 0xFF_FFFF_FFFF, 0xFFFF_FFFF);
if word & mask == want {
self.idx = i + select(is_f, 5, 4);
return Ok(!is_f);
}
}
let (value, end) = read_bool_slow(self.bytes, i)?;
self.idx = end;
Ok(value)
}
#[inline(always)]
pub(crate) fn expect_lit(&mut self, lit: &[u8], code: ErrorCode) -> PResult<()> {
let n = lit.len();
if self.remaining() >= n && &self.bytes[self.idx..self.idx + n] == lit {
self.idx += n;
Ok(())
} else {
Err(code)
}
}
#[inline(always)]
pub fn try_null(&mut self) -> PResult<bool> {
if self.peek() == Some(b'n') {
self.expect_lit(b"null", ErrorCode::ExpectedNull)?;
Ok(true)
} else {
Ok(false)
}
}
#[inline(always)]
pub fn read_u64(&mut self) -> PResult<u64> {
let v = parse_unsigned_u64(self.bytes, &mut self.idx)?;
reject_float_tail(self.bytes, self.idx)?;
Ok(v)
}
#[inline(always)]
pub fn read_i64(&mut self) -> PResult<i64> {
let v = parse_i64(self.bytes, &mut self.idx)?;
reject_float_tail(self.bytes, self.idx)?;
Ok(v)
}
#[inline(always)]
pub fn read_f64(&mut self) -> PResult<f64> {
parse_float::<f64>(self.bytes, &mut self.idx)
}
#[inline(always)]
pub fn read_f32(&mut self) -> PResult<f32> {
parse_float::<f32>(self.bytes, &mut self.idx)
}
pub fn read_u128(&mut self) -> PResult<u128> {
let v = parse_unsigned_u128(self.bytes, &mut self.idx)?;
reject_float_tail(self.bytes, self.idx)?;
Ok(v)
}
pub fn read_i128(&mut self) -> PResult<i128> {
let negative = self.peek() == Some(b'-');
self.idx += negative as usize;
let magnitude = parse_u128(self.bytes, &mut self.idx)?;
let v = if negative {
if magnitude > (i128::MAX as u128) + 1 {
return Err(out_of_range(self.bytes, self.idx));
}
(magnitude as i128).wrapping_neg()
} else {
if magnitude > i128::MAX as u128 {
return Err(out_of_range(self.bytes, self.idx));
}
magnitude as i128
};
reject_float_tail(self.bytes, self.idx)?;
Ok(v)
}
#[inline]
pub fn read_number_str(&mut self) -> PResult<&'de str> {
let start = self.idx;
scan_number(self.bytes, &mut self.idx)?;
Ok(unsafe { core::str::from_utf8_unchecked(&self.bytes[start..self.idx]) })
}
#[inline(always)]
fn scan_body(&mut self, from: usize) -> PResult<::core::result::Result<&'de str, usize>> {
match scan_string(self.bytes, from) {
Some((pos, b'"')) => {
self.idx = pos + 1;
Ok(Ok(unsafe {
core::str::from_utf8_unchecked(&self.bytes[from..pos])
}))
}
Some((pos, b'\\')) => Ok(Err(pos)),
Some(_) => Err(ErrorCode::ControlCharacterInString),
None => Err(ErrorCode::UnexpectedEnd),
}
}
#[inline]
pub fn read_string(&mut self) -> PResult<JsonStr<'de>> {
self.expect(b'"', ErrorCode::ExpectedQuote)?;
self.read_string_body()
}
#[inline]
pub fn read_string_body(&mut self) -> PResult<JsonStr<'de>> {
let start = self.idx;
match self.scan_body(start)? {
Ok(s) => Ok(JsonStr::Borrowed(s)),
Err(first) => {
let mut out = String::new();
self.unescape_into(start, first, &mut out)?;
Ok(JsonStr::Owned(out))
}
}
}
#[inline]
pub fn read_string_into(&mut self, out: &mut String) -> PResult<()> {
self.expect(b'"', ErrorCode::ExpectedQuote)?;
let start = self.idx;
match self.scan_body(start)? {
Ok(s) => {
out.clear();
out.push_str(s);
Ok(())
}
Err(first) => {
out.clear();
self.unescape_into(start, first, out)
}
}
}
#[inline]
pub fn read_str(&mut self) -> PResult<&'de str> {
self.expect(b'"', ErrorCode::ExpectedQuote)?;
let start = self.idx;
match self.scan_body(start)? {
Ok(s) => Ok(s),
Err(_) => Err(ErrorCode::EscapeInBorrowedString),
}
}
fn unescape_into(&mut self, start: usize, first: usize, out: &mut String) -> PResult<()> {
let bytes = unsafe { out.as_mut_vec() };
bytes.extend_from_slice(&self.bytes[start..first]);
let mut i = self.expand_escape(first + 1, bytes)?;
loop {
let stop = match scan_string(self.bytes, i) {
Some((pos, _)) => pos,
None => return Err(ErrorCode::UnexpectedEnd),
};
bytes.extend_from_slice(&self.bytes[i..stop]);
match self.bytes[stop] {
b'"' => {
self.idx = stop + 1;
return Ok(());
}
b'\\' => {
i = self.expand_escape(stop + 1, bytes)?;
}
_ => return Err(ErrorCode::ControlCharacterInString),
}
}
}
fn expand_escape(&self, i: usize, out: &mut Vec<u8>) -> PResult<usize> {
let (ch, next) = self.decode_escape(i)?;
if ch.is_ascii() {
out.push(ch as u8);
} else {
let mut buf = [0u8; 4];
out.extend_from_slice(ch.encode_utf8(&mut buf).as_bytes());
}
Ok(next)
}
#[inline(always)]
fn decode_escape(&self, i: usize) -> PResult<(char, usize)> {
let c = *self.bytes.get(i).ok_or(ErrorCode::UnexpectedEnd)?;
let ch = match c {
b'"' => '"',
b'\\' => '\\',
b'/' => '/',
b'b' => '\u{8}',
b'f' => '\u{c}',
b'n' => '\n',
b'r' => '\r',
b't' => '\t',
b'u' => return self.read_unicode_escape(i + 1),
_ => return Err(ErrorCode::InvalidEscape),
};
Ok((ch, i + 1))
}
fn read_unicode_escape(&self, i: usize) -> PResult<(char, usize)> {
let hi = self.read_hex4(i)?;
let mut next = i + 4;
if (0xD800..0xDC00).contains(&hi) {
if self.bytes.get(next) != Some(&b'\\') || self.bytes.get(next + 1) != Some(&b'u') {
return Err(ErrorCode::InvalidSurrogate);
}
let lo = self.read_hex4(next + 2)?;
if !(0xDC00..0xE000).contains(&lo) {
return Err(ErrorCode::InvalidSurrogate);
}
next += 6;
let cp = 0x1_0000 + ((hi - 0xD800) << 10) + (lo - 0xDC00);
let ch = char::from_u32(cp).ok_or(ErrorCode::InvalidSurrogate)?;
return Ok((ch, next));
}
if (0xDC00..0xE000).contains(&hi) {
return Err(ErrorCode::InvalidSurrogate);
}
let ch = char::from_u32(hi).ok_or(ErrorCode::InvalidSurrogate)?;
Ok((ch, next))
}
#[inline]
fn read_hex4(&self, i: usize) -> PResult<u32> {
if i + 4 > self.bytes.len() {
return Err(ErrorCode::UnexpectedEnd);
}
let mut v = 0u32;
for k in 0..4 {
let d = match self.bytes[i + k] {
c @ b'0'..=b'9' => (c - b'0') as u32,
c @ b'a'..=b'f' => (c - b'a' + 10) as u32,
c @ b'A'..=b'F' => (c - b'A' + 10) as u32,
_ => return Err(ErrorCode::InvalidEscape),
};
v = (v << 4) | d;
}
Ok(v)
}
#[inline(always)]
fn skip_string_body(&mut self) -> PResult<()> {
self.walk_string_body::<false>()
}
fn walk_string_body<const CHECK_ESCAPES: bool>(&mut self) -> PResult<()> {
let mut i = self.idx;
loop {
match scan_string(self.bytes, i) {
Some((pos, b'"')) => {
self.idx = pos + 1;
return Ok(());
}
Some((pos, b'\\')) if CHECK_ESCAPES => {
i = self.decode_escape(pos + 1)?.1;
}
Some((pos, b'\\')) => {
i = pos + 2;
if i > self.bytes.len() {
return Err(ErrorCode::UnexpectedEnd);
}
}
Some(_) => return Err(ErrorCode::ControlCharacterInString),
None => return Err(ErrorCode::UnexpectedEnd),
}
}
}
#[inline]
pub fn skip_value(&mut self) -> PResult<()> {
self.walk_value::<false>()
}
#[inline]
pub(crate) fn skip_value_checked(&mut self) -> PResult<()> {
self.walk_value::<true>()
}
fn walk_value<const CHECK_ESCAPES: bool>(&mut self) -> PResult<()> {
self.skip_ws();
match self.peek() {
Some(b'{') => {
self.idx += 1;
self.nested(|p| {
p.skip_ws();
if p.try_byte(b'}') {
return Ok(());
}
loop {
p.expect(b'"', ErrorCode::ExpectedQuote)?;
p.walk_string_body::<CHECK_ESCAPES>()?;
p.colon()?;
p.walk_value::<CHECK_ESCAPES>()?;
if !p.comma_or_close(b'}')? {
return Ok(());
}
}
})
}
Some(b'[') => {
self.idx += 1;
self.nested(|p| {
p.skip_ws();
if p.try_byte(b']') {
return Ok(());
}
loop {
p.walk_value::<CHECK_ESCAPES>()?;
if !p.comma_or_close(b']')? {
return Ok(());
}
}
})
}
_ => self.walk_scalar::<CHECK_ESCAPES>(),
}
}
#[inline]
pub(crate) fn skip_scalar(&mut self) -> PResult<()> {
self.walk_scalar::<false>()
}
#[inline]
fn walk_scalar<const CHECK_ESCAPES: bool>(&mut self) -> PResult<()> {
match self.peek() {
Some(b'"') => {
self.idx += 1;
self.walk_string_body::<CHECK_ESCAPES>()
}
Some(b't') => self.expect_lit(b"true", ErrorCode::ExpectedTrue),
Some(b'f') => self.expect_lit(b"false", ErrorCode::ExpectedFalse),
Some(b'n') => self.expect_lit(b"null", ErrorCode::ExpectedNull),
Some(c) if c == b'-' || c.is_ascii_digit() => {
let mut i = self.idx;
let n = self.bytes.len();
while i < n {
match self.bytes[i] {
b'0'..=b'9' | b'-' | b'+' | b'.' | b'e' | b'E' => i += 1,
_ => break,
}
}
self.idx = i;
Ok(())
}
None => Err(ErrorCode::UnexpectedEnd),
Some(_) => Err(ErrorCode::UnexpectedCharacter),
}
}
#[inline]
pub fn finish(&mut self) -> PResult<()> {
self.skip_ws();
if self.idx == self.bytes.len() {
Ok(())
} else {
Err(ErrorCode::TrailingContent)
}
}
#[inline(always)]
pub fn read<T: Read<'de>>(&mut self, value: &mut T) -> PResult<()> {
value.read(self)
}
}
const WHITESPACE: [bool; 256] = {
let mut t = [false; 256];
t[b' ' as usize] = true;
t[b'\t' as usize] = true;
t[b'\n' as usize] = true;
t[b'\r' as usize] = true;
t
};
#[inline(always)]
pub(crate) const fn is_ws(c: u8) -> bool {
WHITESPACE[c as usize]
}
#[inline(always)]
pub(crate) const fn scalar_byte(c: u8) -> bool {
c.is_ascii_alphanumeric() || matches!(c, b'-' | b'+' | b'.')
}
#[inline(always)]
pub(crate) fn skip_ws_at<O: Options>(data: &[u8], at: usize) -> usize {
let mut i = at;
while i < data.len() {
match data[i] {
c if is_ws(c) => i += 1,
b'/' if O::ALLOW_COMMENTS => match skip_comment(data, i) {
Some(after) => i = after,
None => break,
},
_ => break,
}
}
i
}
#[cold]
#[inline(never)]
fn read_bool_slow(data: &[u8], idx: usize) -> PResult<(bool, usize)> {
let rest = &data[idx.min(data.len())..];
match rest.first() {
Some(b't') if rest.starts_with(b"true") => Ok((true, idx + 4)),
Some(b't') => Err(ErrorCode::ExpectedTrue),
Some(b'f') if rest.starts_with(b"false") => Ok((false, idx + 5)),
Some(b'f') => Err(ErrorCode::ExpectedFalse),
Some(_) => Err(ErrorCode::UnexpectedCharacter),
None => Err(ErrorCode::UnexpectedEnd),
}
}
#[inline]
pub(crate) fn skip_comment(data: &[u8], at: usize) -> Option<usize> {
let body = at + 2;
match data.get(at + 1)? {
b'/' => Some(find_byte(data, body, b'\n').unwrap_or(data.len())),
b'*' => {
let end = data.get(body..)?.windows(2).position(|w| w == b"*/")?;
Some(body + end + 2)
}
_ => None,
}
}
#[derive(Clone, Debug)]
pub enum JsonStr<'de> {
Borrowed(&'de str),
Owned(String),
}
impl<'de> JsonStr<'de> {
#[inline(always)]
pub fn as_str(&self) -> &str {
match self {
JsonStr::Borrowed(s) => s,
JsonStr::Owned(s) => s,
}
}
#[inline]
pub fn into_string(self) -> String {
match self {
JsonStr::Borrowed(s) => s.to_owned(),
JsonStr::Owned(s) => s,
}
}
}
impl PartialEq for JsonStr<'_> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl Eq for JsonStr<'_> {}
impl core::hash::Hash for JsonStr<'_> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}
impl fmt::Display for JsonStr<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[inline(always)]
fn scan_string(data: &[u8], from: usize) -> Option<(usize, u8)> {
let n = data.len();
let mut i = from;
while i + 8 <= n {
let m = escape_mask(unsafe { load_u64(data, i) });
if m != 0 {
let pos = i + first_match(m);
return Some((pos, data[pos]));
}
i += 8;
}
while i < n {
let c = data[i];
if needs_escape(c) {
return Some((i, c));
}
i += 1;
}
None
}