1use alloc::vec::Vec;
2
3use crate::de::{Layer, LayerEvent, Next};
4use crate::error::{Error, ErrorKind};
5use crate::event::{Atom, Event};
6use crate::ext::RawInput;
7
8#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
42pub struct Limits {
43 max_depth: Option<usize>,
44 max_events: Option<usize>,
45 max_items: Option<usize>,
46 max_len: Option<usize>,
47}
48
49impl Limits {
50 pub const fn new() -> Limits {
52 Limits {
53 max_depth: None,
54 max_events: None,
55 max_items: None,
56 max_len: None,
57 }
58 }
59
60 pub const fn builder() -> LimitsBuilder {
62 LimitsBuilder::new()
63 }
64
65 pub const fn into_builder(self) -> LimitsBuilder {
67 LimitsBuilder { value: self }
68 }
69
70 pub const fn set_max_depth(&mut self, depth: usize) {
75 self.max_depth = Some(depth);
76 }
77
78 pub const fn max_depth(&self) -> Option<usize> {
80 self.max_depth
81 }
82
83 pub const fn set_max_events(&mut self, events: usize) {
87 self.max_events = Some(events);
88 }
89
90 pub const fn max_events(&self) -> Option<usize> {
92 self.max_events
93 }
94
95 pub const fn set_max_items(&mut self, items: usize) {
97 self.max_items = Some(items);
98 }
99
100 pub const fn max_items(&self) -> Option<usize> {
103 self.max_items
104 }
105
106 pub const fn set_max_len(&mut self, len: usize) {
109 self.max_len = Some(len);
110 }
111
112 pub const fn max_len(&self) -> Option<usize> {
114 self.max_len
115 }
116
117 pub(crate) const fn is_unlimited(&self) -> bool {
119 self.max_depth.is_none()
120 && self.max_events.is_none()
121 && self.max_items.is_none()
122 && self.max_len.is_none()
123 }
124}
125
126#[derive(Debug, Clone)]
130#[must_use]
131pub struct LimitsBuilder {
132 value: Limits,
133}
134
135impl LimitsBuilder {
136 pub const fn new() -> LimitsBuilder {
138 LimitsBuilder {
139 value: Limits::new(),
140 }
141 }
142
143 pub const fn max_depth(mut self, depth: usize) -> LimitsBuilder {
147 self.value.set_max_depth(depth);
148 self
149 }
150
151 pub const fn max_events(mut self, events: usize) -> LimitsBuilder {
155 self.value.set_max_events(events);
156 self
157 }
158
159 pub const fn max_items(mut self, items: usize) -> LimitsBuilder {
163 self.value.set_max_items(items);
164 self
165 }
166
167 pub const fn max_len(mut self, len: usize) -> LimitsBuilder {
171 self.value.set_max_len(len);
172 self
173 }
174
175 pub const fn build(self) -> Limits {
177 self.value
178 }
179}
180
181impl Default for LimitsBuilder {
182 fn default() -> LimitsBuilder {
183 LimitsBuilder::new()
184 }
185}
186
187#[doc(hidden)]
192pub struct RawLimits {
193 limits: Limits,
194 events: usize,
195 depth: usize,
196 items: Vec<(bool, usize, bool)>,
198}
199
200impl RawLimits {
201 pub(crate) fn new(limits: Limits, events: usize, depth: usize) -> Self {
202 Self {
203 limits,
204 events,
205 depth,
206 items: Vec::new(),
207 }
208 }
209
210 pub fn event(&mut self, event: Event<'_>) -> Result<(), Error> {
212 self.events += 1;
213 if self.limits.max_events.is_some_and(|max| self.events > max) {
214 return Err(limit_error("too many events"));
215 }
216 if !matches!(event, Event::MapEnd | Event::SeqEnd)
217 && let Some((is_map, count, key)) = self.items.last_mut()
218 {
219 if !*is_map || *key {
220 *count += 1;
221 if self.limits.max_items.is_some_and(|max| *count > max) {
222 return Err(limit_error("too many items"));
223 }
224 }
225 *key = !*key;
226 }
227 match event {
228 Event::MapStart(_) | Event::SeqStart(_) => {
229 if self.limits.max_depth.is_some_and(|max| self.depth >= max) {
230 return Err(limit_error("recursion limit exceeded"));
231 }
232 self.depth += 1;
233 self.items
234 .push((matches!(event, Event::MapStart(_)), 0, true));
235 }
236 Event::MapEnd | Event::SeqEnd => {
237 self.depth -= 1;
238 self.items.pop();
239 }
240 Event::Atom(atom) => {
241 let len = atom_len(&atom);
242 if self.limits.max_len.is_some_and(|max| len > max) {
243 return Err(limit_error("string or bytes too long"));
244 }
245 }
246 }
247 Ok(())
248 }
249}
250
251pub(crate) struct LimitsLayer {
253 limits: Limits,
254 events: usize,
255 items: Vec<(bool, usize)>,
257}
258
259impl LimitsLayer {
260 pub(crate) fn new(limits: Limits) -> LimitsLayer {
261 LimitsLayer {
262 limits,
263 events: 0,
264 items: Vec::new(),
265 }
266 }
267
268 fn count_item(&mut self, is_map_key: bool) -> Result<(), Error> {
270 if let (Some(max), Some((is_map, count))) = (self.limits.max_items, self.items.last_mut())
271 && (!*is_map || is_map_key)
272 {
273 *count += 1;
274 if *count > max {
275 return Err(limit_error("too many items"));
276 }
277 }
278 Ok(())
279 }
280}
281
282fn atom_len(atom: &Atom<'_>) -> usize {
283 match atom {
284 Atom::Str(s) | Atom::Lexical(s) => s.len(),
285 Atom::Bytes(b) => b.len(),
286 Atom::Implicit(value) => value.text().len(),
287 _ => 0,
288 }
289}
290
291#[cold]
292fn limit_error(msg: &'static str) -> Error {
293 Error::new(ErrorKind::LimitExceeded, msg)
294}
295
296impl Layer for LimitsLayer {
297 fn event<'de>(
298 &mut self,
299 event: LayerEvent<'_, 'de>,
300 next: &mut Next<'_, 'de>,
301 ) -> Result<(), Error> {
302 if let Event::Atom(Atom::Ext(ext)) = event.event()
303 && let Some(input) = ext.downcast_value_ref::<RawInput>()
304 {
305 self.count_item(next.state().is_map_key())?;
306 let mut limits = RawLimits::new(self.limits, self.events, next.state().depth());
307 input.check_limits(&mut limits)?;
308 self.events = limits.events;
309 return next.emit(event);
310 }
311 if let Some(max) = self.limits.max_events {
312 self.events += 1;
313 if self.events > max {
314 return Err(limit_error("too many events"));
315 }
316 }
317 let is_map_key = next.state().is_map_key();
318 match event.event() {
319 Event::MapStart(_) | Event::SeqStart(_) => {
320 if self
321 .limits
322 .max_depth
323 .is_some_and(|max| next.state().depth() >= max)
324 {
325 return Err(limit_error("recursion limit exceeded"));
326 }
327 self.count_item(is_map_key)?;
328 if self.limits.max_items.is_some() {
329 self.items
330 .push((matches!(event.event(), Event::MapStart(_)), 0));
331 }
332 }
333 Event::MapEnd | Event::SeqEnd => {
334 self.items.pop();
335 }
336 Event::Atom(atom) => {
337 if let Some(max) = self.limits.max_len {
338 let len = atom_len(atom);
339 if len > max {
340 return Err(limit_error("string or bytes too long"));
341 }
342 }
343 self.count_item(is_map_key)?;
344 }
345 }
346 next.emit(event)
347 }
348}