Skip to main content

qubit_value/value_wire/
value_wire_limits.rs

1// =============================================================================
2//    Copyright (c) 2025 - 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8
9//! Shared resource limits and accounting for JSON wire decoding.
10// qubit-style: allow multiple-public-types
11
12use std::fmt;
13
14use serde::de::{
15    DeserializeSeed,
16    MapAccess,
17    SeqAccess,
18    Visitor,
19};
20
21use super::internal::display_length;
22use super::{
23    ValueWireDecodeError,
24    ValueWireLimitKind,
25};
26use crate::{
27    MultiValuesRef,
28    ValueContainer,
29    ValueRef,
30};
31
32/// Shared limits applied to one complete wire decode.
33#[must_use]
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub struct WireLimits {
36    max_input_bytes: usize,
37    max_depth: usize,
38    max_nodes: usize,
39    max_collection_items: usize,
40    max_map_entries: usize,
41    max_string_bytes: usize,
42    max_numeric_bytes: usize,
43}
44
45impl WireLimits {
46    /// Default maximum complete JSON input length.
47    pub const DEFAULT_MAX_INPUT_BYTES: usize = 1_048_576;
48    /// Default maximum recursive wire depth.
49    pub const DEFAULT_MAX_DEPTH: usize = 64;
50    /// Default maximum decoded node count.
51    pub const DEFAULT_MAX_NODES: usize = 100_000;
52    /// Default maximum elements in one collection.
53    pub const DEFAULT_MAX_COLLECTION_ITEMS: usize = 4_096;
54    /// Default maximum entries in one map.
55    pub const DEFAULT_MAX_MAP_ENTRIES: usize = 4_096;
56    /// Default maximum bytes in one decoded string.
57    pub const DEFAULT_MAX_STRING_BYTES: usize = 256 * 1024;
58    /// Default maximum UTF-8 bytes in one decoded numeric representation.
59    pub const DEFAULT_MAX_NUMERIC_BYTES: usize = 4_096;
60
61    /// Creates shared wire limits with the specified input-byte bound.
62    #[inline(always)]
63    pub const fn new(max_input_bytes: usize) -> Self {
64        Self {
65            max_input_bytes,
66            max_depth: Self::DEFAULT_MAX_DEPTH,
67            max_nodes: Self::DEFAULT_MAX_NODES,
68            max_collection_items: Self::DEFAULT_MAX_COLLECTION_ITEMS,
69            max_map_entries: Self::DEFAULT_MAX_MAP_ENTRIES,
70            max_string_bytes: Self::DEFAULT_MAX_STRING_BYTES,
71            max_numeric_bytes: Self::DEFAULT_MAX_NUMERIC_BYTES,
72        }
73    }
74
75    /// Sets the maximum recursive wire depth.
76    #[inline(always)]
77    #[must_use = "the configured wire depth limit should be used"]
78    pub const fn with_max_depth(mut self, max_depth: usize) -> Self {
79        self.max_depth = max_depth;
80        self
81    }
82
83    /// Sets the maximum decoded node count.
84    #[inline(always)]
85    #[must_use = "the configured wire node limit should be used"]
86    pub const fn with_max_nodes(mut self, max_nodes: usize) -> Self {
87        self.max_nodes = max_nodes;
88        self
89    }
90
91    /// Sets the maximum elements in one collection.
92    #[inline(always)]
93    #[must_use = "the configured collection limit should be used"]
94    pub const fn with_max_collection_items(
95        mut self,
96        max_collection_items: usize,
97    ) -> Self {
98        self.max_collection_items = max_collection_items;
99        self
100    }
101
102    /// Sets the maximum entries in one map.
103    #[inline(always)]
104    #[must_use = "the configured map limit should be used"]
105    pub const fn with_max_map_entries(
106        mut self,
107        max_map_entries: usize,
108    ) -> Self {
109        self.max_map_entries = max_map_entries;
110        self
111    }
112
113    /// Sets the maximum bytes in one decoded string.
114    #[inline(always)]
115    #[must_use = "the configured string limit should be used"]
116    pub const fn with_max_string_bytes(
117        mut self,
118        max_string_bytes: usize,
119    ) -> Self {
120        self.max_string_bytes = max_string_bytes;
121        self
122    }
123
124    /// Sets the maximum UTF-8 bytes in one decoded numeric representation.
125    #[inline(always)]
126    #[must_use = "the configured numeric limit should be used"]
127    pub const fn with_max_numeric_bytes(
128        mut self,
129        max_numeric_bytes: usize,
130    ) -> Self {
131        self.max_numeric_bytes = max_numeric_bytes;
132        self
133    }
134
135    /// Returns the maximum complete input length.
136    #[must_use]
137    #[inline(always)]
138    pub const fn max_input_bytes(self) -> usize {
139        self.max_input_bytes
140    }
141
142    /// Returns the maximum recursive depth.
143    #[must_use]
144    #[inline(always)]
145    pub const fn max_depth(self) -> usize {
146        self.max_depth
147    }
148
149    /// Returns the maximum decoded node count.
150    #[must_use]
151    #[inline(always)]
152    pub const fn max_nodes(self) -> usize {
153        self.max_nodes
154    }
155
156    /// Returns the maximum elements in one collection.
157    #[must_use]
158    #[inline(always)]
159    pub const fn max_collection_items(self) -> usize {
160        self.max_collection_items
161    }
162
163    /// Returns the maximum entries in one map.
164    #[must_use]
165    #[inline(always)]
166    pub const fn max_map_entries(self) -> usize {
167        self.max_map_entries
168    }
169
170    /// Returns the maximum bytes in one decoded string.
171    #[must_use]
172    #[inline(always)]
173    pub const fn max_string_bytes(self) -> usize {
174        self.max_string_bytes
175    }
176
177    /// Returns the maximum UTF-8 bytes in one decoded numeric representation.
178    #[must_use]
179    #[inline(always)]
180    pub const fn max_numeric_bytes(self) -> usize {
181        self.max_numeric_bytes
182    }
183
184    /// Checks a complete input length and starts a shared accounting session.
185    #[inline]
186    pub fn begin(
187        self,
188        input_bytes: usize,
189    ) -> Result<WireBudget, ValueWireDecodeError> {
190        if input_bytes > self.max_input_bytes {
191            return Err(ValueWireDecodeError::InputTooLarge {
192                input_bytes,
193                max_input_bytes: self.max_input_bytes,
194            });
195        }
196        Ok(WireBudget {
197            limits: self,
198            nodes: 0,
199        })
200    }
201
202    /// Preflights one complete JSON document before decoding its runtime
203    /// representation, then starts a semantic accounting session.
204    ///
205    /// The preflight validates complete-input size and JSON syntax while
206    /// traversing the document without materializing a JSON tree. Runtime
207    /// resource limits are charged by the returned budget after decoding so
208    /// embedded protocol wrappers do not consume value-node or depth headroom.
209    ///
210    /// # Errors
211    ///
212    /// Returns an input-size or JSON syntax error before the caller
213    /// deserializes its concrete wire DTO. Semantic resource errors are
214    /// returned by the budget after the DTO has been materialized.
215    /// Normal decode paths should use [`Self::begin`] and let their Serde
216    /// decoder validate syntax once.
217    #[inline]
218    pub fn begin_json(
219        self,
220        input: &[u8],
221    ) -> Result<WireBudget, ValueWireDecodeError> {
222        self.check_json_bytes(input.len())?;
223        let mut deserializer = serde_json::Deserializer::from_slice(input);
224        let mut preflight = JsonPreflightSeed::new(input.len());
225        if let Err(error) = (&mut preflight).deserialize(&mut deserializer) {
226            if let Some(error) = preflight.violation.take() {
227                return Err(error);
228            }
229            return Err(ValueWireDecodeError::InvalidJson(error));
230        }
231        deserializer
232            .end()
233            .map_err(ValueWireDecodeError::InvalidJson)?;
234        self.begin(input.len())
235    }
236
237    /// Checks a complete input length without starting an accounting session.
238    #[inline]
239    pub const fn check_json_bytes(
240        self,
241        input_bytes: usize,
242    ) -> Result<(), ValueWireDecodeError> {
243        if input_bytes > self.max_input_bytes {
244            Err(ValueWireDecodeError::InputTooLarge {
245                input_bytes,
246                max_input_bytes: self.max_input_bytes,
247            })
248        } else {
249            Ok(())
250        }
251    }
252}
253
254impl Default for WireLimits {
255    #[inline(always)]
256    fn default() -> Self {
257        Self::new(Self::DEFAULT_MAX_INPUT_BYTES)
258    }
259}
260
261/// Mutable accounting state shared by one complete wire decode.
262#[must_use]
263#[derive(Debug)]
264pub struct WireBudget {
265    limits: WireLimits,
266    nodes: usize,
267}
268
269impl WireBudget {
270    /// Returns the configured limits for this session.
271    #[inline(always)]
272    pub const fn limits(&self) -> WireLimits {
273        self.limits
274    }
275
276    /// Charges one decoded node.
277    #[inline]
278    pub fn check_node(&mut self) -> Result<(), ValueWireDecodeError> {
279        self.nodes = self.nodes.saturating_add(1);
280        self.check_limit(
281            ValueWireLimitKind::Nodes,
282            self.nodes,
283            self.limits.max_nodes,
284        )
285    }
286
287    /// Checks a recursive depth.
288    #[inline]
289    pub fn check_depth(
290        &self,
291        depth: usize,
292    ) -> Result<(), ValueWireDecodeError> {
293        self.check_limit(
294            ValueWireLimitKind::Depth,
295            depth,
296            self.limits.max_depth,
297        )
298    }
299
300    /// Checks one collection length.
301    #[inline]
302    pub fn check_collection_items(
303        &self,
304        items: usize,
305    ) -> Result<(), ValueWireDecodeError> {
306        self.check_limit(
307            ValueWireLimitKind::CollectionItems,
308            items,
309            self.limits.max_collection_items,
310        )
311    }
312
313    /// Checks one map length.
314    #[inline]
315    pub fn check_map_entries(
316        &self,
317        entries: usize,
318    ) -> Result<(), ValueWireDecodeError> {
319        self.check_limit(
320            ValueWireLimitKind::MapEntries,
321            entries,
322            self.limits.max_map_entries,
323        )
324    }
325
326    /// Checks one decoded string length.
327    #[inline]
328    pub fn check_string_bytes(
329        &self,
330        bytes: usize,
331    ) -> Result<(), ValueWireDecodeError> {
332        self.check_limit(
333            ValueWireLimitKind::StringBytes,
334            bytes,
335            self.limits.max_string_bytes,
336        )
337    }
338
339    /// Checks one decoded numeric representation length in UTF-8 bytes.
340    #[inline]
341    pub fn check_numeric_bytes(
342        &self,
343        bytes: usize,
344    ) -> Result<(), ValueWireDecodeError> {
345        self.check_limit(
346            ValueWireLimitKind::NumericBytes,
347            bytes,
348            self.limits.max_numeric_bytes,
349        )
350    }
351
352    /// Validates a decoded value container against the shared budget.
353    #[inline]
354    pub fn check_container(
355        &mut self,
356        container: &ValueContainer,
357    ) -> Result<(), ValueWireDecodeError> {
358        self.check_container_at(container, 1)
359    }
360
361    /// Validates one decoded value container at `depth`.
362    pub fn check_container_at(
363        &mut self,
364        container: &ValueContainer,
365        depth: usize,
366    ) -> Result<(), ValueWireDecodeError> {
367        self.check_depth(depth)?;
368        match container {
369            ValueContainer::Scalar(value) => {
370                self.check_value_ref(value.view(), depth)
371            }
372            ValueContainer::Collection(values) => {
373                self.check_node()?;
374                self.check_collection_items(values.len())?;
375                self.check_multi_values_ref(values.view(), depth)
376            }
377        }
378    }
379
380    /// Validates one scalar Value against the shared budget.
381    #[inline]
382    pub fn check_value(
383        &mut self,
384        value: &crate::Value,
385    ) -> Result<(), ValueWireDecodeError> {
386        self.check_value_ref(value.view(), 1)
387    }
388
389    /// Validates one homogeneous collection against the shared budget.
390    ///
391    /// # Parameters
392    ///
393    /// * `values` - Collection whose elements are charged to this budget.
394    ///
395    /// # Errors
396    ///
397    /// Returns a resource-limit error when the collection exceeds the
398    /// configured depth, node, item, string, map, or numeric limits.
399    #[inline]
400    pub fn check_multi_values(
401        &mut self,
402        values: &crate::MultiValues,
403    ) -> Result<(), ValueWireDecodeError> {
404        self.check_multi_values_at(values, 1)
405    }
406
407    /// Validates one homogeneous collection at an embedding depth.
408    ///
409    /// # Parameters
410    ///
411    /// * `values` - Collection whose elements are charged to this budget.
412    /// * `depth` - Root-inclusive depth of the collection.
413    ///
414    /// # Errors
415    ///
416    /// Returns a resource-limit error when the collection exceeds the
417    /// configured depth, node, item, string, map, or numeric limits.
418    pub fn check_multi_values_at(
419        &mut self,
420        values: &crate::MultiValues,
421        depth: usize,
422    ) -> Result<(), ValueWireDecodeError> {
423        self.check_depth(depth)?;
424        self.check_node()?;
425        self.check_collection_items(values.len())?;
426        self.check_multi_values_ref(values.view(), depth)
427    }
428
429    /// Validates a named scalar and reuses scalar budget accounting.
430    ///
431    /// # Parameters
432    ///
433    /// * `value` - Named scalar to validate.
434    ///
435    /// # Errors
436    ///
437    /// Returns a resource-limit error for the wrapper name or nested value.
438    #[inline]
439    pub fn check_named_value(
440        &mut self,
441        value: &crate::NamedValue,
442    ) -> Result<(), ValueWireDecodeError> {
443        self.check_named_value_at(value, 1)
444    }
445
446    /// Validates a named scalar at an embedding depth.
447    ///
448    /// # Parameters
449    ///
450    /// * `value` - Named scalar to validate.
451    /// * `depth` - Root-inclusive depth of the named wrapper.
452    ///
453    /// # Errors
454    ///
455    /// Returns a resource-limit error for the wrapper name or nested value.
456    pub fn check_named_value_at(
457        &mut self,
458        value: &crate::NamedValue,
459        depth: usize,
460    ) -> Result<(), ValueWireDecodeError> {
461        self.check_depth(depth)?;
462        self.check_node()?;
463        self.check_string_bytes(value.name().len())?;
464        self.check_value_ref(value.value().view(), depth.saturating_add(1))
465    }
466
467    /// Validates a named collection and reuses collection budget accounting.
468    ///
469    /// # Parameters
470    ///
471    /// * `value` - Named collection to validate.
472    ///
473    /// # Errors
474    ///
475    /// Returns a resource-limit error for the wrapper name or nested values.
476    #[inline]
477    pub fn check_named_multi_values(
478        &mut self,
479        value: &crate::NamedMultiValues,
480    ) -> Result<(), ValueWireDecodeError> {
481        self.check_named_multi_values_at(value, 1)
482    }
483
484    /// Validates a named collection at an embedding depth.
485    ///
486    /// # Parameters
487    ///
488    /// * `value` - Named collection to validate.
489    /// * `depth` - Root-inclusive depth of the named wrapper.
490    ///
491    /// # Errors
492    ///
493    /// Returns a resource-limit error for the wrapper name or nested values.
494    pub fn check_named_multi_values_at(
495        &mut self,
496        value: &crate::NamedMultiValues,
497        depth: usize,
498    ) -> Result<(), ValueWireDecodeError> {
499        self.check_depth(depth)?;
500        self.check_node()?;
501        self.check_string_bytes(value.name().len())?;
502        self.check_multi_values_at(value.values(), depth.saturating_add(1))
503    }
504
505    fn check_value_ref(
506        &mut self,
507        value: ValueRef<'_>,
508        depth: usize,
509    ) -> Result<(), ValueWireDecodeError> {
510        self.check_depth(depth)?;
511        self.check_node()?;
512        match value {
513            ValueRef::Char(value) => self.check_string_bytes(value.len_utf8()),
514            ValueRef::String(value) => self.check_string_bytes(value.len()),
515            ValueRef::StringMap(value) => {
516                self.check_map_entries(value.len())?;
517                for (key, value) in value {
518                    self.check_string_bytes(key.len())?;
519                    self.check_depth(depth.saturating_add(1))?;
520                    self.check_node()?;
521                    self.check_string_bytes(value.len())?;
522                }
523                Ok(())
524            }
525            #[cfg(feature = "json")]
526            ValueRef::Json(value) => {
527                self.check_json(value, depth.saturating_add(1))
528            }
529            #[cfg(feature = "big-integer")]
530            ValueRef::BigInteger(value) => {
531                self.check_numeric_bytes(display_length(value))
532            }
533            #[cfg(feature = "big-decimal")]
534            ValueRef::BigDecimal(value) => {
535                self.check_numeric_bytes(big_decimal_numeric_len(value))
536            }
537            ValueRef::Int8(value) => {
538                self.check_numeric_bytes(display_length(value))
539            }
540            ValueRef::Int16(value) => {
541                self.check_numeric_bytes(display_length(value))
542            }
543            ValueRef::Int32(value) => {
544                self.check_numeric_bytes(display_length(value))
545            }
546            ValueRef::Int64(value) => {
547                self.check_numeric_bytes(display_length(value))
548            }
549            ValueRef::Int128(value) => {
550                self.check_numeric_bytes(display_length(value))
551            }
552            ValueRef::UInt8(value) => {
553                self.check_numeric_bytes(display_length(value))
554            }
555            ValueRef::UInt16(value) => {
556                self.check_numeric_bytes(display_length(value))
557            }
558            ValueRef::UInt32(value) => {
559                self.check_numeric_bytes(display_length(value))
560            }
561            ValueRef::UInt64(value) => {
562                self.check_numeric_bytes(display_length(value))
563            }
564            ValueRef::UInt128(value) => {
565                self.check_numeric_bytes(display_length(value))
566            }
567            ValueRef::Float32(value) => {
568                self.check_numeric_bytes(display_length(value))
569            }
570            ValueRef::Float64(value) => {
571                self.check_numeric_bytes(display_length(value))
572            }
573            #[cfg(feature = "chrono")]
574            ValueRef::Date(value) => {
575                self.check_string_bytes(display_length(value.format("%F")))
576            }
577            #[cfg(feature = "chrono")]
578            ValueRef::Time(value) => self.check_string_bytes(display_length(
579                value.format("%H:%M:%S%.f"),
580            )),
581            #[cfg(feature = "chrono")]
582            ValueRef::DateTime(value) => self.check_string_bytes(
583                display_length(value.format("%Y-%m-%dT%H:%M:%S%.f")),
584            ),
585            #[cfg(feature = "chrono")]
586            ValueRef::Instant(value) => self.check_string_bytes(
587                display_length(value.format("%Y-%m-%dT%H:%M:%S%.fZ")),
588            ),
589            ValueRef::Duration(value) => {
590                self.check_numeric_bytes(display_length(value.as_secs()))?;
591                self.check_numeric_bytes(display_length(value.subsec_nanos()))
592            }
593            #[cfg(feature = "url")]
594            ValueRef::Url(value) => {
595                self.check_string_bytes(value.as_str().len())
596            }
597            ValueRef::Unset(_) | ValueRef::Bool(_) => Ok(()),
598        }
599    }
600
601    /// Validates one scalar value at an embedding depth.
602    ///
603    /// Use this method when the scalar is nested inside an outer wire
604    /// document. The depth is inclusive and should be supplied by the outer
605    /// protocol's accounting traversal.
606    ///
607    /// # Parameters
608    ///
609    /// * `value` - Scalar value to validate.
610    /// * `depth` - Root-inclusive depth of the scalar in the complete document.
611    ///
612    /// # Errors
613    ///
614    /// Returns a resource-limit error when the value exceeds the configured
615    /// depth, node, string, or numeric budget.
616    #[inline(always)]
617    pub fn check_value_at(
618        &mut self,
619        value: &crate::Value,
620        depth: usize,
621    ) -> Result<(), ValueWireDecodeError> {
622        self.check_value_ref(value.view(), depth)
623    }
624
625    fn check_multi_values_ref(
626        &mut self,
627        values: MultiValuesRef<'_>,
628        depth: usize,
629    ) -> Result<(), ValueWireDecodeError> {
630        macro_rules! check_values {
631            ($values:expr) => {{
632                for value in $values {
633                    self.check_value_ref(value, depth.saturating_add(1))?;
634                }
635                Ok(())
636            }};
637        }
638        match values {
639            MultiValuesRef::Unset(_) => Ok(()),
640            MultiValuesRef::Bool(values) => {
641                check_values!(values.iter().map(|_| ValueRef::Bool(false)))
642            }
643            MultiValuesRef::Char(values) => {
644                check_values!(values.iter().copied().map(ValueRef::Char))
645            }
646            MultiValuesRef::Int8(values) => {
647                check_values!(values.iter().copied().map(ValueRef::Int8))
648            }
649            MultiValuesRef::Int16(values) => {
650                check_values!(values.iter().copied().map(ValueRef::Int16))
651            }
652            MultiValuesRef::Int32(values) => {
653                check_values!(values.iter().copied().map(ValueRef::Int32))
654            }
655            MultiValuesRef::Int64(values) => {
656                check_values!(values.iter().copied().map(ValueRef::Int64))
657            }
658            MultiValuesRef::Int128(values) => {
659                check_values!(values.iter().copied().map(ValueRef::Int128))
660            }
661            MultiValuesRef::UInt8(values) => {
662                check_values!(values.iter().copied().map(ValueRef::UInt8))
663            }
664            MultiValuesRef::UInt16(values) => {
665                check_values!(values.iter().copied().map(ValueRef::UInt16))
666            }
667            MultiValuesRef::UInt32(values) => {
668                check_values!(values.iter().copied().map(ValueRef::UInt32))
669            }
670            MultiValuesRef::UInt64(values) => {
671                check_values!(values.iter().copied().map(ValueRef::UInt64))
672            }
673            MultiValuesRef::UInt128(values) => {
674                check_values!(values.iter().copied().map(ValueRef::UInt128))
675            }
676            MultiValuesRef::Float32(values) => {
677                check_values!(values.iter().copied().map(ValueRef::Float32))
678            }
679            MultiValuesRef::Float64(values) => {
680                check_values!(values.iter().copied().map(ValueRef::Float64))
681            }
682            #[cfg(feature = "big-integer")]
683            MultiValuesRef::BigInteger(values) => {
684                check_values!(values.iter().map(ValueRef::BigInteger))
685            }
686            #[cfg(feature = "big-decimal")]
687            MultiValuesRef::BigDecimal(values) => {
688                check_values!(values.iter().map(ValueRef::BigDecimal))
689            }
690            MultiValuesRef::String(values) => {
691                for value in values {
692                    self.check_value_ref(
693                        ValueRef::String(value),
694                        depth.saturating_add(1),
695                    )?;
696                }
697                Ok(())
698            }
699            #[cfg(feature = "chrono")]
700            MultiValuesRef::Date(values) => {
701                check_values!(values.iter().map(ValueRef::Date))
702            }
703            #[cfg(feature = "chrono")]
704            MultiValuesRef::Time(values) => {
705                check_values!(values.iter().map(ValueRef::Time))
706            }
707            #[cfg(feature = "chrono")]
708            MultiValuesRef::DateTime(values) => {
709                check_values!(values.iter().map(ValueRef::DateTime))
710            }
711            #[cfg(feature = "chrono")]
712            MultiValuesRef::Instant(values) => {
713                check_values!(values.iter().map(ValueRef::Instant))
714            }
715            MultiValuesRef::Duration(values) => {
716                check_values!(values.iter().map(ValueRef::Duration))
717            }
718            #[cfg(feature = "url")]
719            MultiValuesRef::Url(values) => {
720                check_values!(values.iter().map(ValueRef::Url))
721            }
722            MultiValuesRef::StringMap(values) => {
723                check_values!(values.iter().map(ValueRef::StringMap))
724            }
725            #[cfg(feature = "json")]
726            MultiValuesRef::Json(values) => {
727                check_values!(values.iter().map(ValueRef::Json))
728            }
729        }
730    }
731
732    #[cfg(feature = "json")]
733    fn check_json(
734        &mut self,
735        value: &serde_json::Value,
736        depth: usize,
737    ) -> Result<(), ValueWireDecodeError> {
738        self.check_depth(depth)?;
739        self.check_node()?;
740        match value {
741            serde_json::Value::Array(values) => {
742                self.check_collection_items(values.len())?;
743                for value in values {
744                    self.check_json(value, depth.saturating_add(1))?;
745                }
746                Ok(())
747            }
748            serde_json::Value::Object(values) => {
749                self.check_map_entries(values.len())?;
750                for (key, value) in values {
751                    self.check_string_bytes(key.len())?;
752                    self.check_json(value, depth.saturating_add(1))?;
753                }
754                Ok(())
755            }
756            serde_json::Value::String(value) => {
757                self.check_string_bytes(value.len())
758            }
759            serde_json::Value::Number(value) => {
760                self.check_numeric_bytes(display_length(value))
761            }
762            serde_json::Value::Null | serde_json::Value::Bool(_) => Ok(()),
763        }
764    }
765
766    fn check_limit(
767        &self,
768        kind: ValueWireLimitKind,
769        value: usize,
770        maximum: usize,
771    ) -> Result<(), ValueWireDecodeError> {
772        if value > maximum {
773            Err(ValueWireDecodeError::LimitExceeded {
774                kind,
775                value,
776                maximum,
777            })
778        } else {
779            Ok(())
780        }
781    }
782}
783
784/// Returns the bounded V1 decimal payload length without expanding `scale`.
785///
786/// V1 represents a decimal as its canonical integer coefficient plus a
787/// separately bounded scale. Formatting the decimal itself can expand a large
788/// negative scale into an arbitrarily long string, which is unrelated to the
789/// encoded coefficient size.
790#[cfg(feature = "big-decimal")]
791#[inline]
792fn big_decimal_numeric_len(value: &bigdecimal::BigDecimal) -> usize {
793    let (coefficient, _) = value.as_bigint_and_scale();
794    display_length(coefficient.as_ref())
795}
796
797/// Parses JSON with input-bounded traversal without materializing a JSON tree
798/// or a wire DTO.
799struct JsonPreflightSeed {
800    limits: WireLimits,
801    nodes: usize,
802    violation: Option<ValueWireDecodeError>,
803}
804
805impl JsonPreflightSeed {
806    #[inline(always)]
807    fn new(input_bytes: usize) -> Self {
808        // Every JSON node and decoded scalar must occupy at least one input
809        // byte. Using the complete input length as the syntax-traversal ceiling
810        // avoids guessing how many wrapper nodes an outer protocol contributes;
811        // exact semantic limits are enforced after runtime decoding.
812        let limits = WireLimits {
813            max_input_bytes: input_bytes,
814            max_depth: input_bytes,
815            max_nodes: input_bytes,
816            max_collection_items: input_bytes,
817            max_map_entries: input_bytes,
818            max_string_bytes: input_bytes,
819            max_numeric_bytes: input_bytes,
820        };
821        Self {
822            limits,
823            nodes: 0,
824            violation: None,
825        }
826    }
827
828    #[inline]
829    fn check_limit<E>(
830        &mut self,
831        kind: ValueWireLimitKind,
832        value: usize,
833        maximum: usize,
834    ) -> Result<(), E>
835    where
836        E: serde::de::Error,
837    {
838        if value > maximum {
839            self.violation = Some(ValueWireDecodeError::LimitExceeded {
840                kind,
841                value,
842                maximum,
843            });
844            Err(E::custom(format_args!(
845                "wire input {kind:?} value {value} exceeds the limit of {maximum}"
846            )))
847        } else {
848            Ok(())
849        }
850    }
851
852    #[inline]
853    fn check_node<E>(&mut self) -> Result<(), E>
854    where
855        E: serde::de::Error,
856    {
857        self.nodes = self.nodes.saturating_add(1);
858        self.check_limit(
859            ValueWireLimitKind::Nodes,
860            self.nodes,
861            self.limits.max_nodes,
862        )
863    }
864
865    #[inline]
866    fn check_depth<E>(&mut self, depth: usize) -> Result<(), E>
867    where
868        E: serde::de::Error,
869    {
870        self.check_limit(
871            ValueWireLimitKind::Depth,
872            depth,
873            self.limits.max_depth,
874        )
875    }
876
877    #[inline]
878    fn check_collection_items<E>(&mut self, items: usize) -> Result<(), E>
879    where
880        E: serde::de::Error,
881    {
882        self.check_limit(
883            ValueWireLimitKind::CollectionItems,
884            items,
885            self.limits.max_collection_items,
886        )
887    }
888
889    #[inline]
890    fn check_map_entries<E>(&mut self, entries: usize) -> Result<(), E>
891    where
892        E: serde::de::Error,
893    {
894        self.check_limit(
895            ValueWireLimitKind::MapEntries,
896            entries,
897            self.limits.max_map_entries,
898        )
899    }
900
901    #[inline]
902    fn check_string_bytes<E>(&mut self, bytes: usize) -> Result<(), E>
903    where
904        E: serde::de::Error,
905    {
906        self.check_limit(
907            ValueWireLimitKind::StringBytes,
908            bytes,
909            self.limits.max_string_bytes,
910        )
911    }
912
913    #[inline]
914    fn check_numeric_bytes<E>(&mut self, bytes: usize) -> Result<(), E>
915    where
916        E: serde::de::Error,
917    {
918        self.check_limit(
919            ValueWireLimitKind::NumericBytes,
920            bytes,
921            self.limits.max_numeric_bytes,
922        )
923    }
924}
925
926impl<'de> DeserializeSeed<'de> for &mut JsonPreflightSeed {
927    type Value = ();
928
929    #[inline]
930    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
931    where
932        D: serde::Deserializer<'de>,
933    {
934        deserializer.deserialize_any(JsonPreflightVisitor {
935            preflight: self,
936            depth: 1,
937        })
938    }
939}
940
941struct JsonPreflightVisitor<'a> {
942    preflight: &'a mut JsonPreflightSeed,
943    depth: usize,
944}
945
946impl JsonPreflightVisitor<'_> {
947    #[inline]
948    fn scalar<E>(&mut self) -> Result<(), E>
949    where
950        E: serde::de::Error,
951    {
952        self.preflight.check_depth(self.depth)?;
953        self.preflight.check_node()
954    }
955
956    #[inline]
957    fn string<E>(&mut self, value: &str) -> Result<(), E>
958    where
959        E: serde::de::Error,
960    {
961        self.scalar()?;
962        self.preflight.check_string_bytes(value.len())
963    }
964
965    #[inline]
966    fn number<E>(&mut self, bytes: usize) -> Result<(), E>
967    where
968        E: serde::de::Error,
969    {
970        self.scalar()?;
971        self.preflight.check_numeric_bytes(bytes)
972    }
973}
974
975impl<'de> Visitor<'de> for JsonPreflightVisitor<'_> {
976    type Value = ();
977
978    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
979        formatter.write_str("a JSON value")
980    }
981
982    fn visit_bool<E>(mut self, _value: bool) -> Result<Self::Value, E>
983    where
984        E: serde::de::Error,
985    {
986        self.scalar()
987    }
988
989    fn visit_i64<E>(mut self, value: i64) -> Result<Self::Value, E>
990    where
991        E: serde::de::Error,
992    {
993        self.number(display_length(value))
994    }
995
996    fn visit_u64<E>(mut self, value: u64) -> Result<Self::Value, E>
997    where
998        E: serde::de::Error,
999    {
1000        self.number(display_length(value))
1001    }
1002
1003    fn visit_f64<E>(mut self, value: f64) -> Result<Self::Value, E>
1004    where
1005        E: serde::de::Error,
1006    {
1007        self.number(display_length(value))
1008    }
1009
1010    fn visit_unit<E>(mut self) -> Result<Self::Value, E>
1011    where
1012        E: serde::de::Error,
1013    {
1014        self.scalar()
1015    }
1016
1017    fn visit_none<E>(mut self) -> Result<Self::Value, E>
1018    where
1019        E: serde::de::Error,
1020    {
1021        self.scalar()
1022    }
1023
1024    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1025    where
1026        D: serde::Deserializer<'de>,
1027    {
1028        (&mut *self.preflight).deserialize(deserializer)
1029    }
1030
1031    fn visit_borrowed_str<E>(
1032        mut self,
1033        value: &'de str,
1034    ) -> Result<Self::Value, E>
1035    where
1036        E: serde::de::Error,
1037    {
1038        self.string(value)
1039    }
1040
1041    fn visit_str<E>(mut self, value: &str) -> Result<Self::Value, E>
1042    where
1043        E: serde::de::Error,
1044    {
1045        self.string(value)
1046    }
1047
1048    fn visit_string<E>(mut self, value: String) -> Result<Self::Value, E>
1049    where
1050        E: serde::de::Error,
1051    {
1052        self.string(&value)
1053    }
1054
1055    fn visit_seq<A>(mut self, mut access: A) -> Result<Self::Value, A::Error>
1056    where
1057        A: SeqAccess<'de>,
1058    {
1059        self.scalar()?;
1060        let mut items: usize = 0;
1061        while access
1062            .next_element_seed(JsonPreflightChildSeed {
1063                preflight: self.preflight,
1064                depth: self.depth.saturating_add(1),
1065            })?
1066            .is_some()
1067        {
1068            items = items.saturating_add(1);
1069            self.preflight.check_collection_items(items)?;
1070        }
1071        Ok(())
1072    }
1073
1074    fn visit_map<A>(mut self, mut access: A) -> Result<Self::Value, A::Error>
1075    where
1076        A: MapAccess<'de>,
1077    {
1078        self.scalar()?;
1079        let Some(first_key) = access.next_key::<String>()? else {
1080            return Ok(());
1081        };
1082        self.preflight.check_string_bytes(first_key.len())?;
1083
1084        let mut entries = 1_usize;
1085        self.preflight.check_map_entries(entries)?;
1086        if first_key == crate::wire::JSON_NUMBER_TOKEN {
1087            let number_text = access.next_value::<String>()?;
1088            let mut next_key = access.next_key::<String>()?;
1089            if next_key.is_none() {
1090                return self.preflight.check_numeric_bytes(number_text.len());
1091            }
1092            // The marker key was part of a real object. Its first value is a
1093            // normal JSON string; the already-read extra key is accounted for
1094            // by the loop below.
1095            self.preflight.check_depth(self.depth.saturating_add(1))?;
1096            self.preflight.check_node()?;
1097            self.preflight.check_string_bytes(number_text.len())?;
1098            while let Some(key) = next_key.take() {
1099                entries = entries.saturating_add(1);
1100                self.preflight.check_map_entries(entries)?;
1101                self.preflight.check_string_bytes(key.len())?;
1102                access.next_value_seed(JsonPreflightChildSeed {
1103                    preflight: self.preflight,
1104                    depth: self.depth.saturating_add(1),
1105                })?;
1106                next_key = access.next_key::<String>()?;
1107            }
1108            return Ok(());
1109        }
1110        access.next_value_seed(JsonPreflightChildSeed {
1111            preflight: self.preflight,
1112            depth: self.depth.saturating_add(1),
1113        })?;
1114        while let Some(key) = access.next_key::<String>()? {
1115            entries = entries.saturating_add(1);
1116            self.preflight.check_map_entries(entries)?;
1117            self.preflight.check_string_bytes(key.len())?;
1118            access.next_value_seed(JsonPreflightChildSeed {
1119                preflight: self.preflight,
1120                depth: self.depth.saturating_add(1),
1121            })?;
1122        }
1123        Ok(())
1124    }
1125}
1126
1127struct JsonPreflightChildSeed<'a> {
1128    preflight: &'a mut JsonPreflightSeed,
1129    depth: usize,
1130}
1131
1132impl<'de> DeserializeSeed<'de> for JsonPreflightChildSeed<'_> {
1133    type Value = ();
1134
1135    #[inline]
1136    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1137    where
1138        D: serde::Deserializer<'de>,
1139    {
1140        deserializer.deserialize_any(JsonPreflightVisitor {
1141            preflight: self.preflight,
1142            depth: self.depth,
1143        })
1144    }
1145}