use crate::error::{Error, Result};
use alloc::vec::Vec;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Position {
Root,
Array,
Object,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum Kind {
Array,
Object,
}
enum Frame {
Array { ready: bool },
Object { pending_value: bool },
}
pub(crate) struct EventState {
frames: Vec<Frame>,
root_written: bool,
separators: bool,
}
impl EventState {
pub(crate) fn new(separators: bool) -> Self {
EventState {
frames: Vec::new(),
root_written: false,
separators,
}
}
pub(crate) fn in_array(&self) -> bool {
matches!(self.frames.last(), Some(Frame::Array { .. }))
}
pub(crate) fn value(&mut self) -> Result<Position> {
match self.frames.last_mut() {
Some(Frame::Array { ready }) => {
if *ready {
*ready = false;
Ok(Position::Array)
} else if self.separators {
Err(Error::custom("array separator required before value"))
} else {
Ok(Position::Array)
}
}
Some(Frame::Object { pending_value }) if *pending_value => {
*pending_value = false;
Ok(Position::Object)
}
Some(Frame::Object { .. }) => Err(Error::custom("object key required before value")),
None if self.root_written => Err(Error::custom("multiple root values")),
None => {
self.root_written = true;
Ok(Position::Root)
}
}
}
pub(crate) fn separator(&mut self) -> Result<()> {
match self.frames.last_mut() {
Some(Frame::Array { ready }) if !*ready => {
*ready = true;
Ok(())
}
Some(Frame::Array { .. }) => Err(Error::custom("array value required after separator")),
_ => Err(Error::custom("array separator outside array")),
}
}
pub(crate) fn begin(&mut self, kind: Kind) -> Result<Position> {
let position = self.value()?;
self.frames.push(match kind {
Kind::Array => Frame::Array { ready: false },
Kind::Object => Frame::Object {
pending_value: false,
},
});
Ok(position)
}
pub(crate) fn key(&mut self) -> Result<()> {
match self.frames.last_mut() {
Some(Frame::Object { pending_value }) if !*pending_value => {
*pending_value = true;
Ok(())
}
Some(Frame::Object { .. }) => Err(Error::custom("object value required after key")),
_ => Err(Error::custom("object key outside object")),
}
}
pub(crate) fn end(&mut self, kind: Kind) -> Result<()> {
let frame = self
.frames
.pop()
.ok_or_else(|| Error::custom("container end without matching start"))?;
match (kind, frame) {
(Kind::Array, Frame::Array { ready: true }) => {
Err(Error::custom("array ended after separator without value"))
}
(Kind::Array, Frame::Array { ready: false }) => Ok(()),
(
Kind::Object,
Frame::Object {
pending_value: false,
},
) => Ok(()),
(
Kind::Object,
Frame::Object {
pending_value: true,
},
) => Err(Error::custom("object ended before keyed value")),
(Kind::Object, Frame::Array { .. }) => {
Err(Error::custom("mismatched object end inside array"))
}
(Kind::Array, Frame::Object { .. }) => {
Err(Error::custom("mismatched array end inside object"))
}
}
}
pub(crate) fn finish(&self) -> Result<()> {
if !self.root_written {
return Err(Error::custom("encoder did not receive a root value"));
}
if !self.frames.is_empty() {
return Err(Error::custom("encoder finished inside a container"));
}
Ok(())
}
}