diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index ea17afd2..a82fe018 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1061,11 +1061,11 @@ impl Deserialize for Duration { } let secs = match secs { Some(secs) => secs, - None => try!(visitor.missing_field("secs")), + None => return Err(::missing_field("secs")), }; let nanos = match nanos { Some(nanos) => nanos, - None => try!(visitor.missing_field("nanos")), + None => return Err(::missing_field("nanos")), }; Ok(Duration::new(secs, nanos)) } diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index c3bccea0..a89ff7ab 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -17,6 +17,10 @@ pub mod impls; pub mod value; mod from_primitive; +// Helpers used by generated code. Not public API. +#[doc(hidden)] +pub mod private; + /////////////////////////////////////////////////////////////////////////////// /// `Error` is a trait that allows a `Deserialize` to generically create a @@ -926,31 +930,6 @@ pub trait MapVisitor { fn size_hint(&self) -> (usize, Option) { (0, None) } - - /// Report that the struct has a field that wasn't deserialized. The - /// MapVisitor may consider this an error or it may return a default value - /// for the field. - /// - /// `Deserialize` implementations should typically use - /// `MapVisitor::missing_field` instead. - fn missing_field_seed(&mut self, _seed: V, field: &'static str) -> Result - where V: DeserializeSeed - { - Err(Error::missing_field(field)) - } - - /// Report that the struct has a field that wasn't deserialized. The - /// MapVisitor may consider this an error or it may return a default value - /// for the field. - /// - /// This method exists as a convenience for `Deserialize` implementations. - /// `MapVisitor` implementations should not need to override the default - /// behavior. - fn missing_field(&mut self, field: &'static str) -> Result - where V: Deserialize, - { - self.missing_field_seed(PhantomData, field) - } } impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor { @@ -1004,20 +983,6 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor { fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } - - #[inline] - fn missing_field_seed(&mut self, seed: V, field: &'static str) -> Result - where V: DeserializeSeed - { - (**self).missing_field_seed(seed, field) - } - - #[inline] - fn missing_field(&mut self, field: &'static str) -> Result - where V: Deserialize - { - (**self).missing_field(field) - } } /////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/de/private.rs b/serde/src/de/private.rs new file mode 100644 index 00000000..92e71cf8 --- /dev/null +++ b/serde/src/de/private.rs @@ -0,0 +1,40 @@ +use core::marker::PhantomData; + +use de::{Deserialize, Deserializer, Error, Visitor}; + +/// If the missing field is of type `Option` then treat is as `None`, +/// otherwise it is an error. +pub fn missing_field(field: &'static str) -> Result + where V: Deserialize, + E: Error +{ + struct MissingFieldDeserializer(&'static str, PhantomData); + + impl Deserializer for MissingFieldDeserializer + where E: Error + { + type Error = E; + + fn deserialize(self, _visitor: V) -> Result + where V: Visitor + { + Err(Error::missing_field(self.0)) + } + + fn deserialize_option(self, visitor: V) -> Result + where V: Visitor + { + visitor.visit_none() + } + + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit seq seq_fixed_size bytes byte_buf map unit_struct + newtype_struct tuple_struct struct struct_field tuple enum + ignored_any + } + } + + let deserializer = MissingFieldDeserializer(field, PhantomData); + Deserialize::deserialize(deserializer) +} diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 32f186ee..bd3d5f53 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -928,7 +928,7 @@ fn expr_is_missing(attrs: &attr::Field) -> Tokens { match attrs.deserialize_with() { None => { quote! { - try!(visitor.missing_field(#name)) + try!(_serde::de::private::missing_field(#name)) } } Some(_) => {