use crate::errors::{DEFAULT_RECURSION_LIMIT, JiterError, JsonType, LinePosition, json_error};
use crate::number_decoder::{NumberAny, NumberFloat, NumberInt, NumberRange};
use crate::parse::{Parser, Peek};
use crate::string_decoder::{StringDecoder, StringDecoderRange, Tape};
use crate::value::{JsonValue, take_value_borrowed, take_value_owned, take_value_skip};
use crate::{JsonError, JsonErrorType, PartialMode};
pub type JiterResult<T> = Result<T, JiterError>;
#[derive(Debug)]
pub struct Jiter<'j> {
data: &'j [u8],
parser: Parser<'j>,
tape: Tape,
allow_inf_nan: bool,
allow_partial_strings: bool,
}
impl Clone for Jiter<'_> {
fn clone(&self) -> Self {
Self {
data: self.data,
parser: self.parser.clone(),
tape: Tape::default(),
allow_inf_nan: self.allow_inf_nan,
allow_partial_strings: self.allow_partial_strings,
}
}
}
impl<'j> Jiter<'j> {
pub fn new(data: &'j [u8]) -> Self {
Self {
data,
parser: Parser::new(data),
tape: Tape::default(),
allow_inf_nan: false,
allow_partial_strings: false,
}
}
pub fn with_allow_inf_nan(mut self) -> Self {
self.allow_inf_nan = true;
self
}
pub fn with_allow_partial_strings(mut self) -> Self {
self.allow_partial_strings = true;
self
}
pub fn current_position(&self) -> LinePosition {
self.parser.current_position()
}
pub fn current_index(&self) -> usize {
self.parser.index
}
pub fn slice_to_current(&self, start: usize) -> &'j [u8] {
&self.data[start..self.current_index()]
}
pub fn error_position(&self, index: usize) -> LinePosition {
LinePosition::find(self.data, index)
}
pub fn peek(&mut self) -> JiterResult<Peek> {
self.parser.peek().map_err(Into::into)
}
pub fn next_null(&mut self) -> JiterResult<()> {
let peek = self.peek()?;
match peek {
Peek::Null => self.known_null(),
_ => Err(self.wrong_type(JsonType::Null, peek)),
}
}
pub fn known_null(&mut self) -> JiterResult<()> {
self.parser.consume_null()?;
Ok(())
}
pub fn next_bool(&mut self) -> JiterResult<bool> {
let peek = self.peek()?;
self.known_bool(peek)
}
pub fn known_bool(&mut self, peek: Peek) -> JiterResult<bool> {
match peek {
Peek::True => {
self.parser.consume_true()?;
Ok(true)
}
Peek::False => {
self.parser.consume_false()?;
Ok(false)
}
_ => Err(self.wrong_type(JsonType::Bool, peek)),
}
}
pub fn next_number(&mut self) -> JiterResult<NumberAny> {
let peek = self.peek()?;
self.known_number(peek)
}
pub fn known_number(&mut self, peek: Peek) -> JiterResult<NumberAny> {
self.parser
.consume_number::<NumberAny>(peek.into_inner(), self.allow_inf_nan)
.map_err(|e| self.maybe_number_error(e, JsonType::Int, peek))
}
pub fn next_int(&mut self) -> JiterResult<NumberInt> {
let peek = self.peek()?;
self.known_int(peek)
}
pub fn known_int(&mut self, peek: Peek) -> JiterResult<NumberInt> {
self.parser
.consume_number::<NumberInt>(peek.into_inner(), self.allow_inf_nan)
.map_err(|e| {
if e.error_type == JsonErrorType::FloatExpectingInt {
JiterError::wrong_type(JsonType::Int, JsonType::Float, self.parser.index)
} else {
self.maybe_number_error(e, JsonType::Int, peek)
}
})
}
pub fn next_float(&mut self) -> JiterResult<f64> {
let peek = self.peek()?;
self.known_float(peek)
}
pub fn known_float(&mut self, peek: Peek) -> JiterResult<f64> {
self.parser
.consume_number::<NumberFloat>(peek.into_inner(), self.allow_inf_nan)
.map_err(|e| self.maybe_number_error(e, JsonType::Float, peek))
}
pub fn next_number_bytes(&mut self) -> JiterResult<&[u8]> {
let peek = self.peek()?;
self.known_number_bytes(peek)
}
fn known_number_bytes(&mut self, peek: Peek) -> JiterResult<&[u8]> {
match self
.parser
.consume_number::<NumberRange>(peek.into_inner(), self.allow_inf_nan)
{
Ok(numbe_range) => Ok(&self.data[numbe_range.range]),
Err(e) => Err(self.maybe_number_error(e, JsonType::Float, peek)),
}
}
pub fn next_str(&mut self) -> JiterResult<&str> {
let peek = self.peek()?;
match peek {
Peek::String => self.known_str(),
_ => Err(self.wrong_type(JsonType::String, peek)),
}
}
pub fn known_str(&mut self) -> JiterResult<&str> {
match self
.parser
.consume_string::<StringDecoder>(&mut self.tape, self.allow_partial_strings)
{
Ok(output) => Ok(output.as_str()),
Err(e) => Err(e.into()),
}
}
pub fn next_bytes(&mut self) -> JiterResult<&[u8]> {
let peek = self.peek()?;
match peek {
Peek::String => self.known_bytes(),
_ => Err(self.wrong_type(JsonType::String, peek)),
}
}
pub fn known_bytes(&mut self) -> JiterResult<&[u8]> {
let range = self
.parser
.consume_string::<StringDecoderRange>(&mut self.tape, self.allow_partial_strings)?;
Ok(&self.data[range])
}
pub fn next_value(&mut self) -> JiterResult<JsonValue<'j>> {
let peek = self.peek()?;
self.known_value(peek)
}
pub fn known_value(&mut self, peek: Peek) -> JiterResult<JsonValue<'j>> {
take_value_borrowed(
peek,
&mut self.parser,
&mut self.tape,
DEFAULT_RECURSION_LIMIT,
self.allow_inf_nan,
PartialMode::Off,
)
.map_err(Into::into)
}
pub fn next_skip(&mut self) -> JiterResult<()> {
let peek = self.peek()?;
self.known_skip(peek)
}
pub fn known_skip(&mut self, peek: Peek) -> JiterResult<()> {
take_value_skip(
peek,
&mut self.parser,
&mut self.tape,
DEFAULT_RECURSION_LIMIT,
self.allow_inf_nan,
)
.map_err(Into::into)
}
pub fn next_value_owned(&mut self) -> JiterResult<JsonValue<'static>> {
let peek = self.peek()?;
self.known_value_owned(peek)
}
pub fn known_value_owned(&mut self, peek: Peek) -> JiterResult<JsonValue<'static>> {
take_value_owned(
peek,
&mut self.parser,
&mut self.tape,
DEFAULT_RECURSION_LIMIT,
self.allow_inf_nan,
PartialMode::Off,
)
.map_err(Into::into)
}
pub fn next_array(&mut self) -> JiterResult<Option<Peek>> {
let peek = self.peek()?;
match peek {
Peek::Array => self.known_array(),
_ => Err(self.wrong_type(JsonType::Array, peek)),
}
}
pub fn known_array(&mut self) -> JiterResult<Option<Peek>> {
self.parser.array_first().map_err(Into::into)
}
pub fn array_step(&mut self) -> JiterResult<Option<Peek>> {
self.parser.array_step().map_err(Into::into)
}
pub fn next_object(&mut self) -> JiterResult<Option<&str>> {
let peek = self.peek()?;
match peek {
Peek::Object => self.known_object(),
_ => Err(self.wrong_type(JsonType::Object, peek)),
}
}
pub fn known_object(&mut self) -> JiterResult<Option<&str>> {
let op_str = self.parser.object_first::<StringDecoder>(&mut self.tape)?;
Ok(op_str.map(|s| s.as_str()))
}
pub fn next_object_bytes(&mut self) -> JiterResult<Option<&[u8]>> {
let peek = self.peek()?;
match peek {
Peek::Object => {
let op_range = self.parser.object_first::<StringDecoderRange>(&mut self.tape)?;
Ok(op_range.map(|r| &self.data[r]))
}
_ => Err(self.wrong_type(JsonType::Object, peek)),
}
}
pub fn next_key(&mut self) -> JiterResult<Option<&str>> {
let strs = self.parser.object_step::<StringDecoder>(&mut self.tape)?;
Ok(strs.map(|s| s.as_str()))
}
pub fn next_key_bytes(&mut self) -> JiterResult<Option<&[u8]>> {
let op_range = self.parser.object_step::<StringDecoderRange>(&mut self.tape)?;
Ok(op_range.map(|r| &self.data[r]))
}
pub fn finish(&mut self) -> JiterResult<()> {
self.parser.finish().map_err(Into::into)
}
fn wrong_type(&self, expected: JsonType, peek: Peek) -> JiterError {
match peek {
Peek::True | Peek::False => JiterError::wrong_type(expected, JsonType::Bool, self.parser.index),
Peek::Null => JiterError::wrong_type(expected, JsonType::Null, self.parser.index),
Peek::String => JiterError::wrong_type(expected, JsonType::String, self.parser.index),
Peek::Array => JiterError::wrong_type(expected, JsonType::Array, self.parser.index),
Peek::Object => JiterError::wrong_type(expected, JsonType::Object, self.parser.index),
_ if peek.is_num() => self.wrong_num(peek.into_inner(), expected),
_ => json_error!(ExpectedSomeValue, self.parser.index).into(),
}
}
fn wrong_num(&self, first: u8, expected: JsonType) -> JiterError {
let mut parser2 = self.parser.clone();
let actual = match parser2.consume_number::<NumberAny>(first, self.allow_inf_nan) {
Ok(NumberAny::Int { .. }) => JsonType::Int,
Ok(NumberAny::Float { .. }) => JsonType::Float,
Err(e) => return e.into(),
};
JiterError::wrong_type(expected, actual, self.parser.index)
}
fn maybe_number_error(&self, e: JsonError, expected: JsonType, peek: Peek) -> JiterError {
if peek.is_num() {
e.into()
} else {
self.wrong_type(expected, peek)
}
}
}