use std::fmt;
use serde::de::{
DeserializeSeed,
MapAccess,
SeqAccess,
Visitor,
};
use super::internal::display_length;
use super::{
ValueWireDecodeError,
ValueWireLimitKind,
};
use crate::{
MultiValuesRef,
ValueContainer,
ValueRef,
};
#[must_use]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WireLimits {
max_input_bytes: usize,
max_depth: usize,
max_nodes: usize,
max_collection_items: usize,
max_map_entries: usize,
max_string_bytes: usize,
max_numeric_bytes: usize,
}
impl WireLimits {
pub const DEFAULT_MAX_INPUT_BYTES: usize = 1_048_576;
pub const DEFAULT_MAX_DEPTH: usize = 64;
pub const DEFAULT_MAX_NODES: usize = 100_000;
pub const DEFAULT_MAX_COLLECTION_ITEMS: usize = 4_096;
pub const DEFAULT_MAX_MAP_ENTRIES: usize = 4_096;
pub const DEFAULT_MAX_STRING_BYTES: usize = 256 * 1024;
pub const DEFAULT_MAX_NUMERIC_BYTES: usize = 4_096;
#[inline(always)]
pub const fn new(max_input_bytes: usize) -> Self {
Self {
max_input_bytes,
max_depth: Self::DEFAULT_MAX_DEPTH,
max_nodes: Self::DEFAULT_MAX_NODES,
max_collection_items: Self::DEFAULT_MAX_COLLECTION_ITEMS,
max_map_entries: Self::DEFAULT_MAX_MAP_ENTRIES,
max_string_bytes: Self::DEFAULT_MAX_STRING_BYTES,
max_numeric_bytes: Self::DEFAULT_MAX_NUMERIC_BYTES,
}
}
#[inline(always)]
#[must_use = "the configured wire depth limit should be used"]
pub const fn with_max_depth(mut self, max_depth: usize) -> Self {
self.max_depth = max_depth;
self
}
#[inline(always)]
#[must_use = "the configured wire node limit should be used"]
pub const fn with_max_nodes(mut self, max_nodes: usize) -> Self {
self.max_nodes = max_nodes;
self
}
#[inline(always)]
#[must_use = "the configured collection limit should be used"]
pub const fn with_max_collection_items(
mut self,
max_collection_items: usize,
) -> Self {
self.max_collection_items = max_collection_items;
self
}
#[inline(always)]
#[must_use = "the configured map limit should be used"]
pub const fn with_max_map_entries(
mut self,
max_map_entries: usize,
) -> Self {
self.max_map_entries = max_map_entries;
self
}
#[inline(always)]
#[must_use = "the configured string limit should be used"]
pub const fn with_max_string_bytes(
mut self,
max_string_bytes: usize,
) -> Self {
self.max_string_bytes = max_string_bytes;
self
}
#[inline(always)]
#[must_use = "the configured numeric limit should be used"]
pub const fn with_max_numeric_bytes(
mut self,
max_numeric_bytes: usize,
) -> Self {
self.max_numeric_bytes = max_numeric_bytes;
self
}
#[must_use]
#[inline(always)]
pub const fn max_input_bytes(self) -> usize {
self.max_input_bytes
}
#[must_use]
#[inline(always)]
pub const fn max_depth(self) -> usize {
self.max_depth
}
#[must_use]
#[inline(always)]
pub const fn max_nodes(self) -> usize {
self.max_nodes
}
#[must_use]
#[inline(always)]
pub const fn max_collection_items(self) -> usize {
self.max_collection_items
}
#[must_use]
#[inline(always)]
pub const fn max_map_entries(self) -> usize {
self.max_map_entries
}
#[must_use]
#[inline(always)]
pub const fn max_string_bytes(self) -> usize {
self.max_string_bytes
}
#[must_use]
#[inline(always)]
pub const fn max_numeric_bytes(self) -> usize {
self.max_numeric_bytes
}
#[inline]
pub fn begin(
self,
input_bytes: usize,
) -> Result<WireBudget, ValueWireDecodeError> {
if input_bytes > self.max_input_bytes {
return Err(ValueWireDecodeError::InputTooLarge {
input_bytes,
max_input_bytes: self.max_input_bytes,
});
}
Ok(WireBudget {
limits: self,
nodes: 0,
})
}
#[inline]
pub fn begin_json(
self,
input: &[u8],
) -> Result<WireBudget, ValueWireDecodeError> {
self.check_json_bytes(input.len())?;
let mut deserializer = serde_json::Deserializer::from_slice(input);
let mut preflight = JsonPreflightSeed::new(input.len());
if let Err(error) = (&mut preflight).deserialize(&mut deserializer) {
if let Some(error) = preflight.violation.take() {
return Err(error);
}
return Err(ValueWireDecodeError::InvalidJson(error));
}
deserializer
.end()
.map_err(ValueWireDecodeError::InvalidJson)?;
self.begin(input.len())
}
#[inline]
pub const fn check_json_bytes(
self,
input_bytes: usize,
) -> Result<(), ValueWireDecodeError> {
if input_bytes > self.max_input_bytes {
Err(ValueWireDecodeError::InputTooLarge {
input_bytes,
max_input_bytes: self.max_input_bytes,
})
} else {
Ok(())
}
}
}
impl Default for WireLimits {
#[inline(always)]
fn default() -> Self {
Self::new(Self::DEFAULT_MAX_INPUT_BYTES)
}
}
#[must_use]
#[derive(Debug)]
pub struct WireBudget {
limits: WireLimits,
nodes: usize,
}
impl WireBudget {
#[inline(always)]
pub const fn limits(&self) -> WireLimits {
self.limits
}
#[inline]
pub fn check_node(&mut self) -> Result<(), ValueWireDecodeError> {
self.nodes = self.nodes.saturating_add(1);
self.check_limit(
ValueWireLimitKind::Nodes,
self.nodes,
self.limits.max_nodes,
)
}
#[inline]
pub fn check_depth(
&self,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_limit(
ValueWireLimitKind::Depth,
depth,
self.limits.max_depth,
)
}
#[inline]
pub fn check_collection_items(
&self,
items: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_limit(
ValueWireLimitKind::CollectionItems,
items,
self.limits.max_collection_items,
)
}
#[inline]
pub fn check_map_entries(
&self,
entries: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_limit(
ValueWireLimitKind::MapEntries,
entries,
self.limits.max_map_entries,
)
}
#[inline]
pub fn check_string_bytes(
&self,
bytes: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_limit(
ValueWireLimitKind::StringBytes,
bytes,
self.limits.max_string_bytes,
)
}
#[inline]
pub fn check_numeric_bytes(
&self,
bytes: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_limit(
ValueWireLimitKind::NumericBytes,
bytes,
self.limits.max_numeric_bytes,
)
}
#[inline]
pub fn check_container(
&mut self,
container: &ValueContainer,
) -> Result<(), ValueWireDecodeError> {
self.check_container_at(container, 1)
}
pub fn check_container_at(
&mut self,
container: &ValueContainer,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_depth(depth)?;
match container {
ValueContainer::Scalar(value) => {
self.check_value_ref(value.view(), depth)
}
ValueContainer::Collection(values) => {
self.check_node()?;
self.check_collection_items(values.len())?;
self.check_multi_values_ref(values.view(), depth)
}
}
}
#[inline]
pub fn check_value(
&mut self,
value: &crate::Value,
) -> Result<(), ValueWireDecodeError> {
self.check_value_ref(value.view(), 1)
}
#[inline]
pub fn check_multi_values(
&mut self,
values: &crate::MultiValues,
) -> Result<(), ValueWireDecodeError> {
self.check_multi_values_at(values, 1)
}
pub fn check_multi_values_at(
&mut self,
values: &crate::MultiValues,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_depth(depth)?;
self.check_node()?;
self.check_collection_items(values.len())?;
self.check_multi_values_ref(values.view(), depth)
}
#[inline]
pub fn check_named_value(
&mut self,
value: &crate::NamedValue,
) -> Result<(), ValueWireDecodeError> {
self.check_named_value_at(value, 1)
}
pub fn check_named_value_at(
&mut self,
value: &crate::NamedValue,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_depth(depth)?;
self.check_node()?;
self.check_string_bytes(value.name().len())?;
self.check_value_ref(value.value().view(), depth.saturating_add(1))
}
#[inline]
pub fn check_named_multi_values(
&mut self,
value: &crate::NamedMultiValues,
) -> Result<(), ValueWireDecodeError> {
self.check_named_multi_values_at(value, 1)
}
pub fn check_named_multi_values_at(
&mut self,
value: &crate::NamedMultiValues,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_depth(depth)?;
self.check_node()?;
self.check_string_bytes(value.name().len())?;
self.check_multi_values_at(value.values(), depth.saturating_add(1))
}
fn check_value_ref(
&mut self,
value: ValueRef<'_>,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_depth(depth)?;
self.check_node()?;
match value {
ValueRef::Char(value) => self.check_string_bytes(value.len_utf8()),
ValueRef::String(value) => self.check_string_bytes(value.len()),
ValueRef::StringMap(value) => {
self.check_map_entries(value.len())?;
for (key, value) in value {
self.check_string_bytes(key.len())?;
self.check_depth(depth.saturating_add(1))?;
self.check_node()?;
self.check_string_bytes(value.len())?;
}
Ok(())
}
#[cfg(feature = "json")]
ValueRef::Json(value) => {
self.check_json(value, depth.saturating_add(1))
}
#[cfg(feature = "big-integer")]
ValueRef::BigInteger(value) => {
self.check_numeric_bytes(display_length(value))
}
#[cfg(feature = "big-decimal")]
ValueRef::BigDecimal(value) => {
self.check_numeric_bytes(big_decimal_numeric_len(value))
}
ValueRef::Int8(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::Int16(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::Int32(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::Int64(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::Int128(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::UInt8(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::UInt16(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::UInt32(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::UInt64(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::UInt128(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::Float32(value) => {
self.check_numeric_bytes(display_length(value))
}
ValueRef::Float64(value) => {
self.check_numeric_bytes(display_length(value))
}
#[cfg(feature = "chrono")]
ValueRef::Date(value) => {
self.check_string_bytes(display_length(value.format("%F")))
}
#[cfg(feature = "chrono")]
ValueRef::Time(value) => self.check_string_bytes(display_length(
value.format("%H:%M:%S%.f"),
)),
#[cfg(feature = "chrono")]
ValueRef::DateTime(value) => self.check_string_bytes(
display_length(value.format("%Y-%m-%dT%H:%M:%S%.f")),
),
#[cfg(feature = "chrono")]
ValueRef::Instant(value) => self.check_string_bytes(
display_length(value.format("%Y-%m-%dT%H:%M:%S%.fZ")),
),
ValueRef::Duration(value) => {
self.check_numeric_bytes(display_length(value.as_secs()))?;
self.check_numeric_bytes(display_length(value.subsec_nanos()))
}
#[cfg(feature = "url")]
ValueRef::Url(value) => {
self.check_string_bytes(value.as_str().len())
}
ValueRef::Unset(_) | ValueRef::Bool(_) => Ok(()),
}
}
#[inline(always)]
pub fn check_value_at(
&mut self,
value: &crate::Value,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_value_ref(value.view(), depth)
}
fn check_multi_values_ref(
&mut self,
values: MultiValuesRef<'_>,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
macro_rules! check_values {
($values:expr) => {{
for value in $values {
self.check_value_ref(value, depth.saturating_add(1))?;
}
Ok(())
}};
}
match values {
MultiValuesRef::Unset(_) => Ok(()),
MultiValuesRef::Bool(values) => {
check_values!(values.iter().map(|_| ValueRef::Bool(false)))
}
MultiValuesRef::Char(values) => {
check_values!(values.iter().copied().map(ValueRef::Char))
}
MultiValuesRef::Int8(values) => {
check_values!(values.iter().copied().map(ValueRef::Int8))
}
MultiValuesRef::Int16(values) => {
check_values!(values.iter().copied().map(ValueRef::Int16))
}
MultiValuesRef::Int32(values) => {
check_values!(values.iter().copied().map(ValueRef::Int32))
}
MultiValuesRef::Int64(values) => {
check_values!(values.iter().copied().map(ValueRef::Int64))
}
MultiValuesRef::Int128(values) => {
check_values!(values.iter().copied().map(ValueRef::Int128))
}
MultiValuesRef::UInt8(values) => {
check_values!(values.iter().copied().map(ValueRef::UInt8))
}
MultiValuesRef::UInt16(values) => {
check_values!(values.iter().copied().map(ValueRef::UInt16))
}
MultiValuesRef::UInt32(values) => {
check_values!(values.iter().copied().map(ValueRef::UInt32))
}
MultiValuesRef::UInt64(values) => {
check_values!(values.iter().copied().map(ValueRef::UInt64))
}
MultiValuesRef::UInt128(values) => {
check_values!(values.iter().copied().map(ValueRef::UInt128))
}
MultiValuesRef::Float32(values) => {
check_values!(values.iter().copied().map(ValueRef::Float32))
}
MultiValuesRef::Float64(values) => {
check_values!(values.iter().copied().map(ValueRef::Float64))
}
#[cfg(feature = "big-integer")]
MultiValuesRef::BigInteger(values) => {
check_values!(values.iter().map(ValueRef::BigInteger))
}
#[cfg(feature = "big-decimal")]
MultiValuesRef::BigDecimal(values) => {
check_values!(values.iter().map(ValueRef::BigDecimal))
}
MultiValuesRef::String(values) => {
for value in values {
self.check_value_ref(
ValueRef::String(value),
depth.saturating_add(1),
)?;
}
Ok(())
}
#[cfg(feature = "chrono")]
MultiValuesRef::Date(values) => {
check_values!(values.iter().map(ValueRef::Date))
}
#[cfg(feature = "chrono")]
MultiValuesRef::Time(values) => {
check_values!(values.iter().map(ValueRef::Time))
}
#[cfg(feature = "chrono")]
MultiValuesRef::DateTime(values) => {
check_values!(values.iter().map(ValueRef::DateTime))
}
#[cfg(feature = "chrono")]
MultiValuesRef::Instant(values) => {
check_values!(values.iter().map(ValueRef::Instant))
}
MultiValuesRef::Duration(values) => {
check_values!(values.iter().map(ValueRef::Duration))
}
#[cfg(feature = "url")]
MultiValuesRef::Url(values) => {
check_values!(values.iter().map(ValueRef::Url))
}
MultiValuesRef::StringMap(values) => {
check_values!(values.iter().map(ValueRef::StringMap))
}
#[cfg(feature = "json")]
MultiValuesRef::Json(values) => {
check_values!(values.iter().map(ValueRef::Json))
}
}
}
#[cfg(feature = "json")]
fn check_json(
&mut self,
value: &serde_json::Value,
depth: usize,
) -> Result<(), ValueWireDecodeError> {
self.check_depth(depth)?;
self.check_node()?;
match value {
serde_json::Value::Array(values) => {
self.check_collection_items(values.len())?;
for value in values {
self.check_json(value, depth.saturating_add(1))?;
}
Ok(())
}
serde_json::Value::Object(values) => {
self.check_map_entries(values.len())?;
for (key, value) in values {
self.check_string_bytes(key.len())?;
self.check_json(value, depth.saturating_add(1))?;
}
Ok(())
}
serde_json::Value::String(value) => {
self.check_string_bytes(value.len())
}
serde_json::Value::Number(value) => {
self.check_numeric_bytes(display_length(value))
}
serde_json::Value::Null | serde_json::Value::Bool(_) => Ok(()),
}
}
fn check_limit(
&self,
kind: ValueWireLimitKind,
value: usize,
maximum: usize,
) -> Result<(), ValueWireDecodeError> {
if value > maximum {
Err(ValueWireDecodeError::LimitExceeded {
kind,
value,
maximum,
})
} else {
Ok(())
}
}
}
#[cfg(feature = "big-decimal")]
#[inline]
fn big_decimal_numeric_len(value: &bigdecimal::BigDecimal) -> usize {
let (coefficient, _) = value.as_bigint_and_scale();
display_length(coefficient.as_ref())
}
struct JsonPreflightSeed {
limits: WireLimits,
nodes: usize,
violation: Option<ValueWireDecodeError>,
}
impl JsonPreflightSeed {
#[inline(always)]
fn new(input_bytes: usize) -> Self {
let limits = WireLimits {
max_input_bytes: input_bytes,
max_depth: input_bytes,
max_nodes: input_bytes,
max_collection_items: input_bytes,
max_map_entries: input_bytes,
max_string_bytes: input_bytes,
max_numeric_bytes: input_bytes,
};
Self {
limits,
nodes: 0,
violation: None,
}
}
#[inline]
fn check_limit<E>(
&mut self,
kind: ValueWireLimitKind,
value: usize,
maximum: usize,
) -> Result<(), E>
where
E: serde::de::Error,
{
if value > maximum {
self.violation = Some(ValueWireDecodeError::LimitExceeded {
kind,
value,
maximum,
});
Err(E::custom(format_args!(
"wire input {kind:?} value {value} exceeds the limit of {maximum}"
)))
} else {
Ok(())
}
}
#[inline]
fn check_node<E>(&mut self) -> Result<(), E>
where
E: serde::de::Error,
{
self.nodes = self.nodes.saturating_add(1);
self.check_limit(
ValueWireLimitKind::Nodes,
self.nodes,
self.limits.max_nodes,
)
}
#[inline]
fn check_depth<E>(&mut self, depth: usize) -> Result<(), E>
where
E: serde::de::Error,
{
self.check_limit(
ValueWireLimitKind::Depth,
depth,
self.limits.max_depth,
)
}
#[inline]
fn check_collection_items<E>(&mut self, items: usize) -> Result<(), E>
where
E: serde::de::Error,
{
self.check_limit(
ValueWireLimitKind::CollectionItems,
items,
self.limits.max_collection_items,
)
}
#[inline]
fn check_map_entries<E>(&mut self, entries: usize) -> Result<(), E>
where
E: serde::de::Error,
{
self.check_limit(
ValueWireLimitKind::MapEntries,
entries,
self.limits.max_map_entries,
)
}
#[inline]
fn check_string_bytes<E>(&mut self, bytes: usize) -> Result<(), E>
where
E: serde::de::Error,
{
self.check_limit(
ValueWireLimitKind::StringBytes,
bytes,
self.limits.max_string_bytes,
)
}
#[inline]
fn check_numeric_bytes<E>(&mut self, bytes: usize) -> Result<(), E>
where
E: serde::de::Error,
{
self.check_limit(
ValueWireLimitKind::NumericBytes,
bytes,
self.limits.max_numeric_bytes,
)
}
}
impl<'de> DeserializeSeed<'de> for &mut JsonPreflightSeed {
type Value = ();
#[inline]
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(JsonPreflightVisitor {
preflight: self,
depth: 1,
})
}
}
struct JsonPreflightVisitor<'a> {
preflight: &'a mut JsonPreflightSeed,
depth: usize,
}
impl JsonPreflightVisitor<'_> {
#[inline]
fn scalar<E>(&mut self) -> Result<(), E>
where
E: serde::de::Error,
{
self.preflight.check_depth(self.depth)?;
self.preflight.check_node()
}
#[inline]
fn string<E>(&mut self, value: &str) -> Result<(), E>
where
E: serde::de::Error,
{
self.scalar()?;
self.preflight.check_string_bytes(value.len())
}
#[inline]
fn number<E>(&mut self, bytes: usize) -> Result<(), E>
where
E: serde::de::Error,
{
self.scalar()?;
self.preflight.check_numeric_bytes(bytes)
}
}
impl<'de> Visitor<'de> for JsonPreflightVisitor<'_> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a JSON value")
}
fn visit_bool<E>(mut self, _value: bool) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.scalar()
}
fn visit_i64<E>(mut self, value: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.number(display_length(value))
}
fn visit_u64<E>(mut self, value: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.number(display_length(value))
}
fn visit_f64<E>(mut self, value: f64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.number(display_length(value))
}
fn visit_unit<E>(mut self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.scalar()
}
fn visit_none<E>(mut self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.scalar()
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
(&mut *self.preflight).deserialize(deserializer)
}
fn visit_borrowed_str<E>(
mut self,
value: &'de str,
) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.string(value)
}
fn visit_str<E>(mut self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.string(value)
}
fn visit_string<E>(mut self, value: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.string(&value)
}
fn visit_seq<A>(mut self, mut access: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
self.scalar()?;
let mut items: usize = 0;
while access
.next_element_seed(JsonPreflightChildSeed {
preflight: self.preflight,
depth: self.depth.saturating_add(1),
})?
.is_some()
{
items = items.saturating_add(1);
self.preflight.check_collection_items(items)?;
}
Ok(())
}
fn visit_map<A>(mut self, mut access: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
self.scalar()?;
let Some(first_key) = access.next_key::<String>()? else {
return Ok(());
};
self.preflight.check_string_bytes(first_key.len())?;
let mut entries = 1_usize;
self.preflight.check_map_entries(entries)?;
if first_key == crate::wire::JSON_NUMBER_TOKEN {
let number_text = access.next_value::<String>()?;
let mut next_key = access.next_key::<String>()?;
if next_key.is_none() {
return self.preflight.check_numeric_bytes(number_text.len());
}
self.preflight.check_depth(self.depth.saturating_add(1))?;
self.preflight.check_node()?;
self.preflight.check_string_bytes(number_text.len())?;
while let Some(key) = next_key.take() {
entries = entries.saturating_add(1);
self.preflight.check_map_entries(entries)?;
self.preflight.check_string_bytes(key.len())?;
access.next_value_seed(JsonPreflightChildSeed {
preflight: self.preflight,
depth: self.depth.saturating_add(1),
})?;
next_key = access.next_key::<String>()?;
}
return Ok(());
}
access.next_value_seed(JsonPreflightChildSeed {
preflight: self.preflight,
depth: self.depth.saturating_add(1),
})?;
while let Some(key) = access.next_key::<String>()? {
entries = entries.saturating_add(1);
self.preflight.check_map_entries(entries)?;
self.preflight.check_string_bytes(key.len())?;
access.next_value_seed(JsonPreflightChildSeed {
preflight: self.preflight,
depth: self.depth.saturating_add(1),
})?;
}
Ok(())
}
}
struct JsonPreflightChildSeed<'a> {
preflight: &'a mut JsonPreflightSeed,
depth: usize,
}
impl<'de> DeserializeSeed<'de> for JsonPreflightChildSeed<'_> {
type Value = ();
#[inline]
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(JsonPreflightVisitor {
preflight: self.preflight,
depth: self.depth,
})
}
}