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 hidden or 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