use crate::State;
use crate::de::driver::DriverCore;
use crate::error::{Error, ErrorKind};
use crate::event::{Atom, Event};
use alloc::boxed::Box;
use alloc::vec::Vec;
pub trait Layer: Send {
fn event<'de>(
&mut self,
event: LayerEvent<'_, 'de>,
next: &mut Next<'_, 'de>,
) -> Result<(), Error>;
}
pub struct LayerEvent<'e, 'de>(Repr<'e, 'de>);
enum Repr<'e, 'de> {
Borrowed(Event<'de>),
Transient(Event<'e>),
}
impl<'e, 'de> LayerEvent<'e, 'de> {
#[inline(always)]
pub fn new(event: Event<'e>) -> LayerEvent<'e, 'de> {
LayerEvent(Repr::Transient(event))
}
#[inline(always)]
pub fn borrowed(event: Event<'de>) -> LayerEvent<'e, 'de> {
LayerEvent(Repr::Borrowed(event))
}
#[inline(always)]
pub fn event(&self) -> &Event<'_> {
match self.0 {
Repr::Borrowed(ref event) => event,
Repr::Transient(ref event) => event,
}
}
pub fn is_borrowed(&self) -> bool {
matches!(self.0, Repr::Borrowed(_))
}
}
pub struct Next<'n, 'de> {
layers: &'n mut [Box<dyn Layer>],
core: &'n mut DriverCore<'de>,
}
impl<'n, 'de> Next<'n, 'de> {
#[inline(always)]
pub(crate) fn new(layers: &'n mut [Box<dyn Layer>], core: &'n mut DriverCore<'de>) -> Self {
Next { layers, core }
}
pub fn state(&self) -> &State {
&self.core.state
}
pub fn state_mut(&mut self) -> &mut State {
&mut self.core.state
}
pub fn emit(&mut self, event: LayerEvent<'_, 'de>) -> Result<(), Error> {
self.core.update_position(event.event());
match self.layers.split_first_mut() {
Some((layer, rest)) => layer.event(event, &mut Next::new(rest, self.core)),
None => match event.0 {
Repr::Borrowed(event) => self.core.dispatch_borrowed(event),
Repr::Transient(event) => self.core.dispatch(event),
},
}
}
}
#[derive(Debug, Clone, Default)]
pub struct Limits {
max_depth: Option<usize>,
max_events: Option<usize>,
max_items: Option<usize>,
max_len: Option<usize>,
events: usize,
items: Vec<(bool, usize)>,
}
impl Limits {
pub const fn new() -> Limits {
Limits {
max_depth: None,
max_events: None,
max_items: None,
max_len: None,
events: 0,
items: Vec::new(),
}
}
pub const fn max_depth(mut self, depth: usize) -> Limits {
self.max_depth = Some(depth);
self
}
pub const fn max_events(mut self, events: usize) -> Limits {
self.max_events = Some(events);
self
}
pub const fn max_items(mut self, items: usize) -> Limits {
self.max_items = Some(items);
self
}
pub const fn max_len(mut self, len: usize) -> Limits {
self.max_len = Some(len);
self
}
fn count_item(&mut self, is_map_key: bool) -> Result<(), Error> {
if let (Some(max), Some((is_map, count))) = (self.max_items, self.items.last_mut())
&& (!*is_map || is_map_key)
{
*count += 1;
if *count > max {
return Err(limit_error("too many items"));
}
}
Ok(())
}
}
#[cold]
fn limit_error(msg: &'static str) -> Error {
Error::new(ErrorKind::Unexpected, msg)
}
impl Layer for Limits {
fn event<'de>(
&mut self,
event: LayerEvent<'_, 'de>,
next: &mut Next<'_, 'de>,
) -> Result<(), Error> {
if let Some(max) = self.max_events {
self.events += 1;
if self.events > max {
return Err(limit_error("too many events"));
}
}
let is_map_key = next.state().is_map_key();
match event.event() {
Event::MapStart(_) | Event::SeqStart(_) => {
if self
.max_depth
.is_some_and(|max| next.state().depth() >= max)
{
return Err(limit_error("recursion limit exceeded"));
}
self.count_item(is_map_key)?;
if self.max_items.is_some() {
self.items
.push((matches!(event.event(), Event::MapStart(_)), 0));
}
}
Event::MapEnd | Event::SeqEnd => {
self.items.pop();
}
Event::Atom(atom) => {
if let Some(max) = self.max_len {
let len = match atom {
Atom::Str(s) | Atom::Lexical(s) => s.len(),
Atom::Bytes(b) => b.len(),
_ => 0,
};
if len > max {
return Err(limit_error("string or bytes too long"));
}
}
self.count_item(is_map_key)?;
}
}
next.emit(event)
}
}