use alloc::vec::Vec;
use crate::de::{Layer, LayerEvent, Next};
use crate::error::{Error, ErrorKind};
use crate::event::{Atom, Event};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Limits {
max_depth: Option<usize>,
max_events: Option<usize>,
max_items: Option<usize>,
max_len: Option<usize>,
}
impl Limits {
pub const fn new() -> Limits {
Limits {
max_depth: None,
max_events: None,
max_items: None,
max_len: None,
}
}
pub const fn builder() -> LimitsBuilder {
LimitsBuilder::new()
}
pub const fn into_builder(self) -> LimitsBuilder {
LimitsBuilder { value: self }
}
pub const fn set_max_depth(&mut self, depth: usize) {
self.max_depth = Some(depth);
}
pub const fn max_depth(&self) -> Option<usize> {
self.max_depth
}
pub const fn set_max_events(&mut self, events: usize) {
self.max_events = Some(events);
}
pub const fn max_events(&self) -> Option<usize> {
self.max_events
}
pub const fn set_max_items(&mut self, items: usize) {
self.max_items = Some(items);
}
pub const fn max_items(&self) -> Option<usize> {
self.max_items
}
pub const fn set_max_len(&mut self, len: usize) {
self.max_len = Some(len);
}
pub const fn max_len(&self) -> Option<usize> {
self.max_len
}
pub(crate) const fn is_unlimited(&self) -> bool {
self.max_depth.is_none()
&& self.max_events.is_none()
&& self.max_items.is_none()
&& self.max_len.is_none()
}
}
#[derive(Debug, Clone)]
#[must_use]
pub struct LimitsBuilder {
value: Limits,
}
impl LimitsBuilder {
pub const fn new() -> LimitsBuilder {
LimitsBuilder {
value: Limits::new(),
}
}
pub const fn max_depth(mut self, depth: usize) -> LimitsBuilder {
self.value.set_max_depth(depth);
self
}
pub const fn max_events(mut self, events: usize) -> LimitsBuilder {
self.value.set_max_events(events);
self
}
pub const fn max_items(mut self, items: usize) -> LimitsBuilder {
self.value.set_max_items(items);
self
}
pub const fn max_len(mut self, len: usize) -> LimitsBuilder {
self.value.set_max_len(len);
self
}
pub const fn build(self) -> Limits {
self.value
}
}
impl Default for LimitsBuilder {
fn default() -> LimitsBuilder {
LimitsBuilder::new()
}
}
pub(crate) struct LimitsLayer {
limits: Limits,
events: usize,
items: Vec<(bool, usize)>,
}
impl LimitsLayer {
pub(crate) fn new(limits: Limits) -> LimitsLayer {
LimitsLayer {
limits,
events: 0,
items: Vec::new(),
}
}
fn count_item(&mut self, is_map_key: bool) -> Result<(), Error> {
if let (Some(max), Some((is_map, count))) = (self.limits.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::LimitExceeded, msg)
}
impl Layer for LimitsLayer {
fn event<'de>(
&mut self,
event: LayerEvent<'_, 'de>,
next: &mut Next<'_, 'de>,
) -> Result<(), Error> {
if let Some(max) = self.limits.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
.limits
.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.limits.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.limits.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)
}
}