Created
April 29, 2022 19:13
-
-
Save Lucretiel/b110ead0adfacfd8c65c13d65fa76ffd to your computer and use it in GitHub Desktop.
serde deserializer adapter that limits recursion depth
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub mod sort; | |
use serde::de; | |
#[derive(Debug, Clone, Copy)] | |
pub struct DepthLimiter<T> { | |
depth: usize, | |
inner: T, | |
} | |
impl<'de, T: de::Deserializer<'de>> DepthLimiter<T> { | |
pub fn new(item: T, depth: usize) -> Self { | |
Self { inner: item, depth } | |
} | |
} | |
impl<'de, D> de::Deserializer<'de> for DepthLimiter<D> | |
where | |
D: de::Deserializer<'de>, | |
{ | |
type Error = D::Error; | |
#[inline] | |
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_any(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_bool(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_i8(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_i16(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_i32(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_i64(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_u8(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_u16(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_u32(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_u64(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
serde::serde_if_integer128! { | |
#[inline] | |
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_i128(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_u128(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
} | |
#[inline] | |
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_f32(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_f64(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_char(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_str(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_string(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_bytes(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_byte_buf(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_option(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_unit(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_unit_struct<V>( | |
self, | |
name: &'static str, | |
visitor: V, | |
) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_unit_struct( | |
name, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
#[inline] | |
fn deserialize_newtype_struct<V>( | |
self, | |
name: &'static str, | |
visitor: V, | |
) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_newtype_struct( | |
name, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
#[inline] | |
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_seq(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_tuple( | |
len, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
#[inline] | |
fn deserialize_tuple_struct<V>( | |
self, | |
name: &'static str, | |
len: usize, | |
visitor: V, | |
) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_tuple_struct( | |
name, | |
len, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
#[inline] | |
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_map(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_struct<V>( | |
self, | |
name: &'static str, | |
fields: &'static [&'static str], | |
visitor: V, | |
) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_struct( | |
name, | |
fields, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
#[inline] | |
fn deserialize_enum<V>( | |
self, | |
name: &'static str, | |
variants: &'static [&'static str], | |
visitor: V, | |
) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_enum( | |
name, | |
variants, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
#[inline] | |
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_identifier(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.deserialize_ignored_any(DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}) | |
} | |
#[inline] | |
fn is_human_readable(&self) -> bool { | |
self.inner.is_human_readable() | |
} | |
} | |
impl<'de, V> de::Visitor<'de> for DepthLimiter<V> | |
where | |
V: de::Visitor<'de>, | |
{ | |
type Value = V::Value; | |
#[inline] | |
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { | |
self.inner.expecting(formatter) | |
} | |
#[inline] | |
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_bool(v) | |
} | |
#[inline] | |
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_i8(v) | |
} | |
#[inline] | |
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_i16(v) | |
} | |
#[inline] | |
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_i32(v) | |
} | |
#[inline] | |
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_i64(v) | |
} | |
#[inline] | |
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_u8(v) | |
} | |
#[inline] | |
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_u16(v) | |
} | |
#[inline] | |
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_u32(v) | |
} | |
#[inline] | |
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_u64(v) | |
} | |
serde::serde_if_integer128! { | |
#[inline] | |
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_i128(v) | |
} | |
#[inline] | |
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_u128(v) | |
} | |
} | |
#[inline] | |
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_f32(v) | |
} | |
#[inline] | |
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_f64(v) | |
} | |
#[inline] | |
fn visit_char<E>(self, v: char) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_char(v) | |
} | |
#[inline] | |
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_str(v) | |
} | |
#[inline] | |
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_borrowed_str(v) | |
} | |
#[inline] | |
fn visit_string<E>(self, v: String) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_string(v) | |
} | |
#[inline] | |
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_bytes(v) | |
} | |
#[inline] | |
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_borrowed_bytes(v) | |
} | |
#[inline] | |
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_byte_buf(v) | |
} | |
#[inline] | |
fn visit_none<E>(self) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_none() | |
} | |
#[inline] | |
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> | |
where | |
D: serde::Deserializer<'de>, | |
{ | |
self.inner.visit_some(DepthLimiter { | |
inner: deserializer, | |
depth: self | |
.depth | |
.checked_sub(1) | |
.ok_or_else(|| de::Error::custom("exceeded recursion limit"))?, | |
}) | |
} | |
#[inline] | |
fn visit_unit<E>(self) -> Result<Self::Value, E> | |
where | |
E: de::Error, | |
{ | |
self.inner.visit_unit() | |
} | |
#[inline] | |
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error> | |
where | |
D: serde::Deserializer<'de>, | |
{ | |
self.inner.visit_newtype_struct(DepthLimiter { | |
inner: deserializer, | |
depth: self | |
.depth | |
.checked_sub(1) | |
.ok_or_else(|| de::Error::custom("exceeded recursion limit"))?, | |
}) | |
} | |
#[inline] | |
fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error> | |
where | |
A: de::SeqAccess<'de>, | |
{ | |
self.inner.visit_seq(DepthLimiter { | |
inner: seq, | |
depth: self | |
.depth | |
.checked_sub(1) | |
.ok_or_else(|| de::Error::custom("exceeded recursion limit"))?, | |
}) | |
} | |
#[inline] | |
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error> | |
where | |
A: de::MapAccess<'de>, | |
{ | |
self.inner.visit_map(DepthLimiter { | |
inner: map, | |
depth: self | |
.depth | |
.checked_sub(1) | |
.ok_or_else(|| de::Error::custom("exceeded recursion limit"))?, | |
}) | |
} | |
#[inline] | |
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error> | |
where | |
A: de::EnumAccess<'de>, | |
{ | |
self.inner.visit_enum(DepthLimiter { | |
inner: data, | |
depth: self | |
.depth | |
.checked_sub(1) | |
.ok_or_else(|| de::Error::custom("exceeded recursion limit"))?, | |
}) | |
} | |
// TODO: __private_visit_untagged_option? | |
} | |
impl<'de, S> de::SeqAccess<'de> for DepthLimiter<S> | |
where | |
S: de::SeqAccess<'de>, | |
{ | |
type Error = S::Error; | |
#[inline] | |
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> | |
where | |
T: de::DeserializeSeed<'de>, | |
{ | |
self.inner.next_element_seed(DepthLimiter { | |
depth: self.depth, | |
inner: seed, | |
}) | |
} | |
} | |
impl<'de, M> de::MapAccess<'de> for DepthLimiter<M> | |
where | |
M: de::MapAccess<'de>, | |
{ | |
type Error = M::Error; | |
#[inline] | |
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> | |
where | |
K: de::DeserializeSeed<'de>, | |
{ | |
self.inner.next_key_seed(DepthLimiter { | |
depth: self.depth, | |
inner: seed, | |
}) | |
} | |
#[inline] | |
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::DeserializeSeed<'de>, | |
{ | |
self.inner.next_value_seed(DepthLimiter { | |
depth: self.depth, | |
inner: seed, | |
}) | |
} | |
#[inline] | |
fn next_entry_seed<K, V>( | |
&mut self, | |
kseed: K, | |
vseed: V, | |
) -> Result<Option<(K::Value, V::Value)>, Self::Error> | |
where | |
K: de::DeserializeSeed<'de>, | |
V: de::DeserializeSeed<'de>, | |
{ | |
self.inner.next_entry_seed( | |
DepthLimiter { | |
depth: self.depth, | |
inner: kseed, | |
}, | |
DepthLimiter { | |
depth: self.depth, | |
inner: vseed, | |
}, | |
) | |
} | |
} | |
impl<'de, E> de::EnumAccess<'de> for DepthLimiter<E> | |
where | |
E: de::EnumAccess<'de>, | |
{ | |
type Error = E::Error; | |
type Variant = DepthLimiter<E::Variant>; | |
#[inline] | |
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> | |
where | |
V: de::DeserializeSeed<'de>, | |
{ | |
let depth = self.depth; | |
self.inner | |
.variant_seed(DepthLimiter { depth, inner: seed }) | |
.map(|(value, variant)| { | |
( | |
value, | |
DepthLimiter { | |
inner: variant, | |
depth, | |
}, | |
) | |
}) | |
} | |
} | |
impl<'de, A> de::VariantAccess<'de> for DepthLimiter<A> | |
where | |
A: de::VariantAccess<'de>, | |
{ | |
type Error = A::Error; | |
#[inline] | |
fn unit_variant(self) -> Result<(), Self::Error> { | |
self.inner.unit_variant() | |
} | |
#[inline] | |
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error> | |
where | |
T: de::DeserializeSeed<'de>, | |
{ | |
self.inner.newtype_variant_seed(DepthLimiter { | |
depth: self.depth, | |
inner: seed, | |
}) | |
} | |
#[inline] | |
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.tuple_variant( | |
len, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
#[inline] | |
fn struct_variant<V>( | |
self, | |
fields: &'static [&'static str], | |
visitor: V, | |
) -> Result<V::Value, Self::Error> | |
where | |
V: de::Visitor<'de>, | |
{ | |
self.inner.struct_variant( | |
fields, | |
DepthLimiter { | |
depth: self.depth, | |
inner: visitor, | |
}, | |
) | |
} | |
} | |
impl<'de, S> de::DeserializeSeed<'de> for DepthLimiter<S> | |
where | |
S: de::DeserializeSeed<'de>, | |
{ | |
type Value = S::Value; | |
#[inline] | |
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> | |
where | |
D: serde::Deserializer<'de>, | |
{ | |
self.inner.deserialize(DepthLimiter { | |
inner: deserializer, | |
depth: self.depth, | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment