From ef205ef70ad30ec284a81827133e6fa93b542afb Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 19 Sep 2021 09:42:33 -0300 Subject: Fix MayBe not being shallow Sadly also a breaking change. Ah well. --- Cargo.toml | 2 +- src/maybe.rs | 1013 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- tests/maybe.rs | 11 + 3 files changed, 1015 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 69db765..1c4c931 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde-util" -version = "0.2.0" +version = "0.3.0" authors = ["SoniEx2 "] license-file = "LICENSE.txt" description = "Soni's Serde Utilities" diff --git a/src/maybe.rs b/src/maybe.rs index 9b2c419..27f436b 100644 --- a/src/maybe.rs +++ b/src/maybe.rs @@ -1,25 +1,37 @@ +#![allow(unused_parens)] + +use std::fmt::Formatter; + use serde::Deserialize; use serde::Deserializer; +use serde::de::DeserializeSeed; +use serde::de::EnumAccess; +use serde::de::MapAccess; +use serde::de::SeqAccess; +use serde::de::VariantAccess; +use serde::de::Visitor; -/// Something that may be an `T`. +/// Something that may be of the kind of `T`. /// -/// If a value cannot be deserialized as a `T`, this will *discard* the value -/// and provide an `MayBe::IsNot`. +/// If a value doesn't have the kind of `T`, this will *discard* the value and +/// provide an `MayBe::IsNot`. Nevertheless, if the value does have the kind of +/// `T` but cannot be deserialized by `T`, this will also fail to deserialize, +/// making this wrapper "shallow". +/// +/// For example, `struct`s have the same kind as a JSON object, `{}`, If the +/// contents of said JSON object don't match what the `struct` is expecting, +/// like if the `struct Foo { bar: u32 }` is being matched, as `MayBe`, +/// against `{"bar": ""}`, then that is an error. However, matching the same +/// `MayBe` against a JSON array, `[]` would not lead to an error, but +/// to an `MayBe::IsNot`. /// /// Can only be used with self-describing formats, like JSON. -#[derive(Deserialize)] -#[serde(untagged)] #[derive(Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum MayBe { Is(T), - #[serde(deserialize_with = "ignore_any")] IsNot, } -fn ignore_any<'de, D: Deserializer<'de>>(d: D) -> Result<(), D::Error> { - serde::de::IgnoredAny::deserialize(d).map(|_| ()) -} - // FIXME decide on Default // This enum is analogous to Result, *not* Option. // @@ -107,3 +119,984 @@ impl From for MayBe { MayBe::Is(thing) } } + +// actual deserialize + +struct MayBeDer<'a, D>(&'a mut bool, D); + +struct MayBeVis<'a, V>(&'a mut bool, V); + +// acts as Deserializer, MapAccess, SeqAccess and EnumAccess, depending on T. +struct DeepDer<'a, T>(&'a mut bool, T); + +#[derive(Deserialize)] +#[serde(untagged)] +enum MayBeHelper { + #[serde(deserialize_with="may_be")] + #[serde(bound = "T: Deserialize<'de>")] + Value(MayBe), +} + +fn may_be<'de, D: Deserializer<'de>, T: Deserialize<'de>>( + d: D, +) -> Result, D::Error> { + let mut depth: bool = false; + match T::deserialize(MayBeDer(&mut depth, d)) { + Ok(t) => Ok(MayBe::Is(t)), + Err(_) if !depth => Ok(MayBe::IsNot), + Err(e) => Err(e), + } +} + +impl<'de, T: Deserialize<'de>> Deserialize<'de> for MayBe { + fn deserialize>(d: D) -> Result { + MayBeHelper::::deserialize(d).map(|MayBeHelper::Value(v): _| v) + } +} + +impl<'a, 'de: 'a, V: Visitor<'de>> Visitor<'de> for MayBeVis<'a, V> { + type Value = V::Value; + + fn expecting(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result { + let MayBeVis(_depth, inner) = self; + inner.expecting(formatter) + } + + fn visit_bool( + self, + v: bool, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_bool(v) + } + + fn visit_i8( + self, + v: i8, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_i8(v) + } + + fn visit_i16( + self, + v: i16, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_i16(v) + } + + fn visit_i32( + self, + v: i32, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_i32(v) + } + + fn visit_i64( + self, + v: i64, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_i64(v) + } + + fn visit_i128( + self, + v: i128, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_i128(v) + } + + fn visit_u8( + self, + v: u8, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_u8(v) + } + + fn visit_u16( + self, + v: u16, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_u16(v) + } + + fn visit_u32( + self, + v: u32, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_u32(v) + } + + fn visit_u64( + self, + v: u64, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_u64(v) + } + + fn visit_u128( + self, + v: u128, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_u128(v) + } + + fn visit_f32( + self, + v: f32, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_f32(v) + } + + fn visit_f64( + self, + v: f64, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_f64(v) + } + + fn visit_char( + self, + v: char, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_char(v) + } + + fn visit_str( + self, + v: &str, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_str(v) + } + + fn visit_borrowed_str( + self, + v: &'de str, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_borrowed_str(v) + } + + fn visit_string( + self, + v: String, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_string(v) + } + + fn visit_bytes( + self, + v: &[u8], + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_bytes(v) + } + + fn visit_borrowed_bytes( + self, + v: &'de [u8], + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_borrowed_bytes(v) + } + + fn visit_byte_buf( + self, + v: Vec, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_byte_buf(v) + } + + fn visit_none( + self, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_none() + } + + fn visit_some>( + self, + deserializer: D, + ) -> Result { + let MayBeVis(depth, inner) = self; + inner.visit_some(DeepDer(depth, deserializer)) + } + + fn visit_unit( + self, + ) -> Result { + let MayBeVis(_depth, inner) = self; + inner.visit_unit() + } + + fn visit_newtype_struct>( + self, + deserializer: D, + ) -> Result { + let MayBeVis(depth, inner) = self; + inner.visit_newtype_struct(DeepDer(depth, deserializer)) + } + + fn visit_seq>( + self, + seq: A, + ) -> Result { + let MayBeVis(depth, inner) = self; + inner.visit_seq(DeepDer(depth, seq)) + } + + fn visit_map>( + self, + map: A, + ) -> Result { + let MayBeVis(depth, inner) = self; + inner.visit_map(DeepDer(depth, map)) + } + + fn visit_enum>( + self, + data: A, + ) -> Result { + let MayBeVis(depth, inner) = self; + inner.visit_enum(DeepDer(depth, data)) + } +} + +impl<'a, 'de: 'a, D: Deserializer<'de>> Deserializer<'de> for MayBeDer<'a, D> { + type Error = D::Error; + + fn deserialize_any>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_any(MayBeVis(depth, visitor)) + } + + fn deserialize_bool>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_bool(MayBeVis(depth, visitor)) + } + + fn deserialize_i8>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_i8(MayBeVis(depth, visitor)) + } + + fn deserialize_i16>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_i16(MayBeVis(depth, visitor)) + } + + fn deserialize_i32>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_i32(MayBeVis(depth, visitor)) + } + + fn deserialize_i64>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_i64(MayBeVis(depth, visitor)) + } + + fn deserialize_u8>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_u8(MayBeVis(depth, visitor)) + } + + fn deserialize_u16>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_u16(MayBeVis(depth, visitor)) + } + + fn deserialize_u32>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_u32(MayBeVis(depth, visitor)) + } + + fn deserialize_u64>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_u64(MayBeVis(depth, visitor)) + } + + fn deserialize_f32>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_f32(MayBeVis(depth, visitor)) + } + + fn deserialize_f64>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_f64(MayBeVis(depth, visitor)) + } + + fn deserialize_char>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_char(MayBeVis(depth, visitor)) + } + + fn deserialize_str>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_str(MayBeVis(depth, visitor)) + } + + fn deserialize_string>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_string(MayBeVis(depth, visitor)) + } + + fn deserialize_bytes>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_bytes(MayBeVis(depth, visitor)) + } + + fn deserialize_byte_buf>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_byte_buf(MayBeVis(depth, visitor)) + } + + fn deserialize_option>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_option(MayBeVis(depth, visitor)) + } + + fn deserialize_unit>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_unit(MayBeVis(depth, visitor)) + } + + fn deserialize_unit_struct>( + self, + name: &'static str, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_unit_struct(name, MayBeVis(depth, visitor)) + } + + fn deserialize_newtype_struct>( + self, + name: &'static str, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_newtype_struct(name, MayBeVis(depth, visitor)) + } + + fn deserialize_seq>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_seq(MayBeVis(depth, visitor)) + } + + fn deserialize_tuple>( + self, + len: usize, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_tuple(len, MayBeVis(depth, visitor)) + } + + fn deserialize_tuple_struct>( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_tuple_struct(name, len, MayBeVis(depth, visitor)) + } + + fn deserialize_map>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_map(MayBeVis(depth, visitor)) + } + + fn deserialize_struct>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_struct(name, fields, MayBeVis(depth, visitor)) + } + + fn deserialize_enum>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_enum(name, variants, MayBeVis(depth, visitor)) + } + + fn deserialize_identifier>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_identifier(MayBeVis(depth, visitor)) + } + + fn deserialize_ignored_any>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_ignored_any(MayBeVis(depth, visitor)) + } + + fn deserialize_i128>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_i128(MayBeVis(depth, visitor)) + } + + fn deserialize_u128>( + self, + visitor: V, + ) -> Result { + let MayBeDer(depth, inner) = self; + inner.deserialize_u128(MayBeVis(depth, visitor)) + } + + fn is_human_readable(&self) -> bool { + let MayBeDer(_depth, inner) = self; + inner.is_human_readable() + } +} + +impl<'a, 'de: 'a, A: VariantAccess<'de>> VariantAccess<'de> for DeepDer<'a, A> { + type Error = A::Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + let DeepDer(depth, inner) = self; + *depth = true; + inner.unit_variant() + } + + fn newtype_variant_seed>( + self, + seed: T, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.newtype_variant_seed(seed) + } + + fn tuple_variant>( + self, + len: usize, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.tuple_variant(len, visitor) + } + + fn struct_variant>( + self, + fields: &'static [&'static str], + visitor: V + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.struct_variant(fields, visitor) + } + + fn newtype_variant>( + self, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.newtype_variant() + } +} + +impl<'a, 'de: 'a, A: EnumAccess<'de>> EnumAccess<'de> for DeepDer<'a, A> { + type Error = A::Error; + + type Variant = DeepDer<'a, A::Variant>; + + fn variant_seed>( + self, + seed: V, + ) -> Result<(V::Value, Self::Variant), Self::Error> { + let DeepDer(depth, inner) = self; + *depth = true; + inner.variant_seed(seed).map(move |(a, b)| { + (a, DeepDer(depth, b)) + }) + } + + fn variant>( + self, + ) -> Result<(V, Self::Variant), Self::Error> { + let DeepDer(depth, inner) = self; + *depth = true; + inner.variant().map(move |(a, b)| { + (a, DeepDer(depth, b)) + }) + } +} + +impl<'a, 'de: 'a, A: SeqAccess<'de>> SeqAccess<'de> for DeepDer<'a, A> { + type Error = A::Error; + + fn next_element_seed>( + &mut self, + seed: T, + ) -> Result, Self::Error> { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_element_seed(seed) + } + + fn next_element>( + &mut self, + ) -> Result, Self::Error> { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_element() + } + + fn size_hint(&self) -> Option { + let DeepDer(_depth, inner) = self; + inner.size_hint() + } +} + +impl<'a, 'de: 'a, A: MapAccess<'de>> MapAccess<'de> for DeepDer<'a, A> { + type Error = A::Error; + + fn next_key_seed>( + &mut self, + seed: K, + ) -> Result, Self::Error> { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_key_seed(seed) + } + + fn next_value_seed>( + &mut self, + seed: V, + ) -> Result { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_value_seed(seed) + } + + fn next_entry_seed, V: DeserializeSeed<'de>>( + &mut self, + kseed: K, + vseed: V, + ) -> Result, Self::Error> { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_entry_seed(kseed, vseed) + } + + fn next_key>( + &mut self, + ) -> Result, Self::Error> { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_key() + } + + fn next_value>( + &mut self, + ) -> Result { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_value() + } + + fn next_entry, V: Deserialize<'de>>( + &mut self, + ) -> Result, Self::Error> { + let DeepDer(ref mut depth, inner) = self; + **depth = true; + inner.next_entry() + } + + fn size_hint(&self) -> Option { + let DeepDer(_depth, inner) = self; + inner.size_hint() + } +} + +impl<'a, 'de: 'a, D: Deserializer<'de>> Deserializer<'de> for DeepDer<'a, D> { + type Error = D::Error; + + fn deserialize_any>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_any((visitor)) + } + + fn deserialize_bool>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_bool((visitor)) + } + + fn deserialize_i8>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_i8((visitor)) + } + + fn deserialize_i16>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_i16((visitor)) + } + + fn deserialize_i32>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_i32((visitor)) + } + + fn deserialize_i64>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_i64((visitor)) + } + + fn deserialize_u8>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_u8((visitor)) + } + + fn deserialize_u16>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_u16((visitor)) + } + + fn deserialize_u32>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_u32((visitor)) + } + + fn deserialize_u64>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_u64((visitor)) + } + + fn deserialize_f32>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_f32((visitor)) + } + + fn deserialize_f64>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_f64((visitor)) + } + + fn deserialize_char>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_char((visitor)) + } + + fn deserialize_str>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_str((visitor)) + } + + fn deserialize_string>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_string((visitor)) + } + + fn deserialize_bytes>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_bytes((visitor)) + } + + fn deserialize_byte_buf>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_byte_buf((visitor)) + } + + fn deserialize_option>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_option((visitor)) + } + + fn deserialize_unit>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_unit((visitor)) + } + + fn deserialize_unit_struct>( + self, + name: &'static str, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_unit_struct(name, (visitor)) + } + + fn deserialize_newtype_struct>( + self, + name: &'static str, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_newtype_struct(name, (visitor)) + } + + fn deserialize_seq>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_seq((visitor)) + } + + fn deserialize_tuple>( + self, + len: usize, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_tuple(len, (visitor)) + } + + fn deserialize_tuple_struct>( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_tuple_struct(name, len, (visitor)) + } + + fn deserialize_map>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_map((visitor)) + } + + fn deserialize_struct>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_struct(name, fields, (visitor)) + } + + fn deserialize_enum>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_enum(name, variants, (visitor)) + } + + fn deserialize_identifier>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_identifier((visitor)) + } + + fn deserialize_ignored_any>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_ignored_any((visitor)) + } + + fn deserialize_i128>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_i128((visitor)) + } + + fn deserialize_u128>( + self, + visitor: V, + ) -> Result { + let DeepDer(depth, inner) = self; + *depth = true; + inner.deserialize_u128((visitor)) + } + + fn is_human_readable(&self) -> bool { + let DeepDer(_depth, inner) = self; + inner.is_human_readable() + } +} diff --git a/tests/maybe.rs b/tests/maybe.rs index 1437195..702f0c5 100644 --- a/tests/maybe.rs +++ b/tests/maybe.rs @@ -47,3 +47,14 @@ fn test_not_t_in_struct() { let json = "{\"bar\": []}"; assert!(from_str::(json).unwrap().bar.is_not()); } + +#[test] +fn test_shallow() { + #[derive(Deserialize)] + struct Foo { + #[serde(rename = "bar")] + _bar: f64, + } + let json = "{\"bar\": []}"; + assert!(from_str::>(json).is_err()); +} -- cgit 1.4.1