Standardize behavior of missing fields

This commit is contained in:
David Tolnay 2017-01-20 00:18:11 -08:00
parent 88149fc0c3
commit 42bc63bed8
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
4 changed files with 47 additions and 42 deletions

View File

@ -1061,11 +1061,11 @@ impl Deserialize for Duration {
}
let secs = match secs {
Some(secs) => secs,
None => try!(visitor.missing_field("secs")),
None => return Err(<V::Error as Error>::missing_field("secs")),
};
let nanos = match nanos {
Some(nanos) => nanos,
None => try!(visitor.missing_field("nanos")),
None => return Err(<V::Error as Error>::missing_field("nanos")),
};
Ok(Duration::new(secs, nanos))
}

View File

@ -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<usize>) {
(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<V>(&mut self, _seed: V, field: &'static str) -> Result<V::Value, Self::Error>
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<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
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<usize>) {
(**self).size_hint()
}
#[inline]
fn missing_field_seed<V>(&mut self, seed: V, field: &'static str) -> Result<V::Value, Self::Error>
where V: DeserializeSeed
{
(**self).missing_field_seed(seed, field)
}
#[inline]
fn missing_field<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
where V: Deserialize
{
(**self).missing_field(field)
}
}
///////////////////////////////////////////////////////////////////////////////

40
serde/src/de/private.rs Normal file
View File

@ -0,0 +1,40 @@
use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
where V: Deserialize,
E: Error
{
struct MissingFieldDeserializer<E>(&'static str, PhantomData<E>);
impl<E> Deserializer for MissingFieldDeserializer<E>
where E: Error
{
type Error = E;
fn deserialize<V>(self, _visitor: V) -> Result<V::Value, E>
where V: Visitor
{
Err(Error::missing_field(self.0))
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
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)
}

View File

@ -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(_) => {