use crate::error::{Error, ErrorKind};
use crate::event::{Event, JsonStr};
use crate::lexer::{DEFAULT_MAX_DEPTH, Frame, Lexer};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum State {
Start,
DocumentEnd,
ArrayValueOrEnd,
ArrayCommaOrEnd,
ObjectKeyOrEnd,
ObjectColon,
ObjectValue,
ObjectCommaOrEnd,
}
#[derive(Debug)]
pub struct Parser<'input, const MAX_DEPTH: usize = DEFAULT_MAX_DEPTH> {
lex: Lexer<'input, MAX_DEPTH>,
state: State,
}
impl<'input, const MAX_DEPTH: usize> Parser<'input, MAX_DEPTH> {
#[must_use]
pub const fn new(input: &'input [u8]) -> Self {
Self {
lex: Lexer::new(input),
state: State::Start,
}
}
pub const fn lexer(&mut self) -> &mut Lexer<'input, MAX_DEPTH> {
&mut self.lex
}
#[must_use]
pub const fn position(&self) -> crate::error::Position {
self.lex.position()
}
#[must_use]
pub const fn input(&self) -> &'input [u8] {
self.lex.input()
}
pub fn next_event(&mut self) -> Result<Option<Event>, Error> {
self.lex.skip_whitespace();
match self.state {
State::Start => self.ev_start(),
State::DocumentEnd => self.ev_document_end(),
State::ArrayValueOrEnd => self.ev_array_value_or_end(),
State::ArrayCommaOrEnd => self.ev_array_comma_or_end(),
State::ObjectKeyOrEnd => self.ev_object_key_or_end(),
State::ObjectColon => self.ev_object_colon(),
State::ObjectValue => self.ev_object_value(),
State::ObjectCommaOrEnd => self.ev_object_comma_or_end(),
}
}
fn ev_start(&mut self) -> Result<Option<Event>, Error> {
match self.lex.peek() {
None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
Some(_) => {
let ev = self.lex.read_value()?;
self.state = state_after_value(&ev, State::DocumentEnd);
Ok(Some(ev))
}
}
}
fn ev_document_end(&self) -> Result<Option<Event>, Error> {
if self.lex.peek().is_some() {
Err(self.lex.err(ErrorKind::TrailingData))
} else {
Ok(None)
}
}
fn ev_array_value_or_end(&mut self) -> Result<Option<Event>, Error> {
match self.lex.peek() {
Some(b']') => {
self.lex.bump();
Ok(Some(self.close_container(Frame::Array)?))
}
Some(_) => {
let ev = self.lex.read_value()?;
self.state = state_after_value(&ev, State::ArrayCommaOrEnd);
Ok(Some(ev))
}
None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
}
}
fn ev_array_comma_or_end(&mut self) -> Result<Option<Event>, Error> {
match self.lex.peek() {
Some(b',') => {
self.lex.bump();
self.lex.skip_whitespace();
if self.lex.peek() == Some(b']') {
return Err(self.lex.err(ErrorKind::UnexpectedByte(b']')));
}
let ev = self.lex.read_value()?;
self.state = state_after_value(&ev, State::ArrayCommaOrEnd);
Ok(Some(ev))
}
Some(b']') => {
self.lex.bump();
Ok(Some(self.close_container(Frame::Array)?))
}
Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
}
}
fn ev_object_key_or_end(&mut self) -> Result<Option<Event>, Error> {
match self.lex.peek() {
Some(b'}') => {
self.lex.bump();
Ok(Some(self.close_container(Frame::Object)?))
}
Some(b'"') => {
let s = self.lex.read_string()?;
self.state = State::ObjectColon;
Ok(Some(Event::Key(s)))
}
Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
}
}
fn ev_object_colon(&mut self) -> Result<Option<Event>, Error> {
match self.lex.peek() {
Some(b':') => {
self.lex.bump();
self.lex.skip_whitespace();
let ev = self.lex.read_value()?;
self.state = state_after_value(&ev, State::ObjectCommaOrEnd);
Ok(Some(ev))
}
Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
}
}
fn ev_object_value(&mut self) -> Result<Option<Event>, Error> {
let ev = self.lex.read_value()?;
self.state = state_after_value(&ev, State::ObjectCommaOrEnd);
Ok(Some(ev))
}
fn ev_object_comma_or_end(&mut self) -> Result<Option<Event>, Error> {
match self.lex.peek() {
Some(b',') => {
self.lex.bump();
self.lex.skip_whitespace();
if self.lex.peek() == Some(b'}') {
return Err(self.lex.err(ErrorKind::UnexpectedByte(b'}')));
}
self.ev_object_key_or_end()
}
Some(b'}') => {
self.lex.bump();
self.close_container(Frame::Object).map(Some)
}
Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
}
}
fn close_container(&mut self, expected: Frame) -> Result<Event, Error> {
self.lex.pop_frame(expected)?;
self.state = match self.lex.stack.top() {
None => State::DocumentEnd,
Some(Frame::Array) => State::ArrayCommaOrEnd,
Some(Frame::Object) => State::ObjectCommaOrEnd,
};
Ok(match expected {
Frame::Array => Event::EndArray,
Frame::Object => Event::EndObject,
})
}
pub fn parse_i64_value(&mut self) -> Result<i64, Error> {
self.lex.parse_i64_value()
}
pub fn parse_str_value(&mut self) -> Result<&'input str, Error> {
self.lex.parse_str_value()
}
pub fn array_start(&mut self) -> Result<bool, Error> {
let empty = self.lex.array_start()?;
if empty {
self.state = match self.lex.stack.top() {
None => State::DocumentEnd,
Some(Frame::Array) => State::ArrayCommaOrEnd,
Some(Frame::Object) => State::ObjectCommaOrEnd,
};
} else {
self.state = State::ArrayValueOrEnd;
}
Ok(empty)
}
pub fn array_continue(&mut self, end_byte: u8) -> Result<bool, Error> {
let closed = self.lex.array_continue(end_byte)?;
if closed {
self.state = match self.lex.stack.top() {
None => State::DocumentEnd,
Some(Frame::Array) => State::ArrayCommaOrEnd,
Some(Frame::Object) => State::ObjectCommaOrEnd,
};
}
Ok(closed)
}
pub fn object_first_key(&mut self) -> Result<Option<&'input str>, Error> {
let key = self.lex.object_first_key()?;
self.state = match key {
None => match self.lex.stack.top() {
None => State::DocumentEnd,
Some(Frame::Array) => State::ArrayCommaOrEnd,
Some(Frame::Object) => State::ObjectCommaOrEnd,
},
Some(_) => State::ObjectValue,
};
Ok(key)
}
pub fn object_next_key(&mut self) -> Result<Option<&'input str>, Error> {
let key = self.lex.object_next_key()?;
self.state = match key {
None => match self.lex.stack.top() {
None => State::DocumentEnd,
Some(Frame::Array) => State::ArrayCommaOrEnd,
Some(Frame::Object) => State::ObjectCommaOrEnd,
},
Some(_) => State::ObjectValue,
};
Ok(key)
}
pub fn object_first_key_lex(&mut self) -> Result<Option<JsonStr>, Error> {
let key = self.lex.object_first_key_lex()?;
self.state = match key {
None => match self.lex.stack.top() {
None => State::DocumentEnd,
Some(Frame::Array) => State::ArrayCommaOrEnd,
Some(Frame::Object) => State::ObjectCommaOrEnd,
},
Some(_) => State::ObjectValue,
};
Ok(key)
}
pub fn object_next_key_lex(&mut self) -> Result<Option<JsonStr>, Error> {
let key = self.lex.object_next_key_lex()?;
self.state = match key {
None => match self.lex.stack.top() {
None => State::DocumentEnd,
Some(Frame::Array) => State::ArrayCommaOrEnd,
Some(Frame::Object) => State::ObjectCommaOrEnd,
},
Some(_) => State::ObjectValue,
};
Ok(key)
}
}
#[inline]
const fn state_after_value(ev: &Event, scalar_next: State) -> State {
match ev {
Event::StartObject => State::ObjectKeyOrEnd,
Event::StartArray => State::ArrayValueOrEnd,
_ => scalar_next,
}
}