Merge pull request #134 from erickt/err

Add Error::length_mismatch, Error::type_mismatch, and de::Type
This commit is contained in:
Erick Tryzelaar 2015-08-10 10:07:51 -07:00
commit c5541cddeb
4 changed files with 92 additions and 40 deletions

View File

@ -34,6 +34,7 @@ use de::{
Error,
MapVisitor,
SeqVisitor,
Type,
VariantVisitor,
Visitor,
};
@ -85,7 +86,7 @@ impl Visitor for BoolVisitor {
match s.trim() {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(Error::syntax("expected `true` or `false`")),
_ => Err(Error::type_mismatch(Type::Bool)),
}
}
}
@ -101,14 +102,14 @@ impl Deserialize for bool {
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_deserialize_num_method {
($src_ty:ty, $method:ident, $from_method:ident) => {
($src_ty:ty, $method:ident, $from_method:ident, $ty:expr) => {
#[inline]
fn $method<E>(&mut self, v: $src_ty) -> Result<T, E>
where E: Error,
{
match FromPrimitive::$from_method(v) {
Some(v) => Ok(v),
None => Err(Error::syntax("expected a number")),
None => Err(Error::type_mismatch($ty)),
}
}
}
@ -132,24 +133,24 @@ impl<
> Visitor for PrimitiveVisitor<T> {
type Value = T;
impl_deserialize_num_method!(isize, visit_isize, from_isize);
impl_deserialize_num_method!(i8, visit_i8, from_i8);
impl_deserialize_num_method!(i16, visit_i16, from_i16);
impl_deserialize_num_method!(i32, visit_i32, from_i32);
impl_deserialize_num_method!(i64, visit_i64, from_i64);
impl_deserialize_num_method!(usize, visit_usize, from_usize);
impl_deserialize_num_method!(u8, visit_u8, from_u8);
impl_deserialize_num_method!(u16, visit_u16, from_u16);
impl_deserialize_num_method!(u32, visit_u32, from_u32);
impl_deserialize_num_method!(u64, visit_u64, from_u64);
impl_deserialize_num_method!(f32, visit_f32, from_f32);
impl_deserialize_num_method!(f64, visit_f64, from_f64);
impl_deserialize_num_method!(isize, visit_isize, from_isize, Type::Isize);
impl_deserialize_num_method!(i8, visit_i8, from_i8, Type::I8);
impl_deserialize_num_method!(i16, visit_i16, from_i16, Type::I16);
impl_deserialize_num_method!(i32, visit_i32, from_i32, Type::I32);
impl_deserialize_num_method!(i64, visit_i64, from_i64, Type::I64);
impl_deserialize_num_method!(usize, visit_usize, from_usize, Type::Usize);
impl_deserialize_num_method!(u8, visit_u8, from_u8, Type::U8);
impl_deserialize_num_method!(u16, visit_u16, from_u16, Type::U16);
impl_deserialize_num_method!(u32, visit_u32, from_u32, Type::U32);
impl_deserialize_num_method!(u64, visit_u64, from_u64, Type::U64);
impl_deserialize_num_method!(f32, visit_f32, from_f32, Type::F32);
impl_deserialize_num_method!(f64, visit_f64, from_f64, Type::F64);
#[inline]
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
where E: Error,
{
str::FromStr::from_str(v.trim()).or(Err(Error::syntax("expected a str")))
str::FromStr::from_str(v.trim()).or(Err(Error::type_mismatch(Type::Str)))
}
}
@ -200,7 +201,7 @@ impl Visitor for CharVisitor {
let mut iter = v.chars();
if let Some(v) = iter.next() {
if iter.next().is_some() {
Err(Error::syntax("expected a character"))
Err(Error::type_mismatch(Type::Char))
} else {
Ok(v)
}
@ -243,7 +244,7 @@ impl Visitor for StringVisitor {
{
match str::from_utf8(v) {
Ok(s) => Ok(s.to_string()),
Err(_) => Err(Error::syntax("expected utf8 `&[u8]`")),
Err(_) => Err(Error::type_mismatch(Type::String)),
}
}
@ -252,7 +253,7 @@ impl Visitor for StringVisitor {
{
match String::from_utf8(v) {
Ok(s) => Ok(s),
Err(_) => Err(Error::syntax("expected utf8 `&[u8]`")),
Err(_) => Err(Error::type_mismatch(Type::String)),
}
}
}
@ -900,7 +901,7 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
_ => {
match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_field(value)),
Err(_) => Err(Error::syntax("expected a `&[u8]`")),
Err(_) => Err(Error::type_mismatch(Type::String)),
}
}
}

View File

@ -5,16 +5,67 @@ pub mod value;
///////////////////////////////////////////////////////////////////////////////
pub trait Error {
/// `Error` is a trait that allows a `Deserialize` to generically create a
/// `Deserializer` error.
pub trait Error: Sized {
/// Raised when there is general error when deserializing a type.
fn syntax(msg: &str) -> Self;
/// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments.
fn length_mismatch(_len: usize) -> Self {
Error::syntax("incorrect length")
}
/// Raised when a `Deserialize` was passed an incorrect type.
fn type_mismatch(_type: Type) -> Self {
Error::syntax("incorrect type")
}
/// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
fn end_of_stream() -> Self;
/// Raised when a `Deserialize` struct type received an unexpected struct field.
fn unknown_field(field: &str) -> Self;
/// Raised when a `Deserialize` struct type did not receive a field.
fn missing_field(field: &'static str) -> Self;
}
/// `Type` represents all the primitive types that can be deserialized. This is used by
/// `Error::kind_mismatch`.
pub enum Type {
Bool,
Usize,
U8,
U16,
U32,
U64,
Isize,
I8,
I16,
I32,
I64,
F32,
F64,
Char,
Str,
String,
Unit,
Option,
Seq,
Map,
UnitStruct,
NewtypeStruct,
TupleStruct,
Struct,
Tuple,
Enum,
StructVariant,
TupleVariant,
UnitVariant,
Bytes,
}
///////////////////////////////////////////////////////////////////////////////
pub trait Deserialize {
@ -304,7 +355,7 @@ pub trait Visitor {
fn visit_bool<E>(&mut self, _v: bool) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected a bool"))
Err(Error::type_mismatch(Type::Bool))
}
fn visit_isize<E>(&mut self, v: isize) -> Result<Self::Value, E>
@ -334,7 +385,7 @@ pub trait Visitor {
fn visit_i64<E>(&mut self, _v: i64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected a i64"))
Err(Error::type_mismatch(Type::I64))
}
fn visit_usize<E>(&mut self, v: usize) -> Result<Self::Value, E>
@ -364,7 +415,7 @@ pub trait Visitor {
fn visit_u64<E>(&mut self, _v: u64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected a u64"))
Err(Error::type_mismatch(Type::U64))
}
fn visit_f32<E>(&mut self, v: f32) -> Result<Self::Value, E>
@ -376,7 +427,7 @@ pub trait Visitor {
fn visit_f64<E>(&mut self, _v: f64) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected a f64"))
Err(Error::type_mismatch(Type::F64))
}
#[inline]
@ -391,7 +442,7 @@ pub trait Visitor {
fn visit_str<E>(&mut self, _v: &str) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected a str"))
Err(Error::type_mismatch(Type::Str))
}
#[inline]
@ -404,7 +455,7 @@ pub trait Visitor {
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected a unit"))
Err(Error::type_mismatch(Type::Unit))
}
#[inline]
@ -417,37 +468,37 @@ pub trait Visitor {
fn visit_none<E>(&mut self) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected an Option::None"))
Err(Error::type_mismatch(Type::Option))
}
fn visit_some<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
Err(Error::syntax("expected an Option::Some"))
Err(Error::type_mismatch(Type::Option))
}
fn visit_newtype_struct<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
Err(Error::syntax("expected a newtype struct"))
Err(Error::type_mismatch(Type::NewtypeStruct))
}
fn visit_seq<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
Err(Error::syntax("expected a sequence"))
Err(Error::type_mismatch(Type::Seq))
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
Err(Error::syntax("expected a map"))
Err(Error::type_mismatch(Type::Map))
}
fn visit_bytes<E>(&mut self, _v: &[u8]) -> Result<Self::Value, E>
where E: Error,
{
Err(Error::syntax("expected a &[u8]"))
Err(Error::type_mismatch(Type::Bytes))
}
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
@ -593,7 +644,7 @@ pub trait VariantVisitor {
/// `visit_unit` is called when deserializing a variant with no values.
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Err(Error::syntax("expected a univ variant"))
Err(Error::type_mismatch(Type::UnitVariant))
}
/// `visit_newtype` is called when deserializing a variant with a single value. By default this
@ -612,7 +663,7 @@ pub trait VariantVisitor {
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::syntax("expected a tuple variant"))
Err(Error::type_mismatch(Type::TupleVariant))
}
/// `visit_struct` is called when deserializing a struct-like variant.
@ -621,7 +672,7 @@ pub trait VariantVisitor {
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::syntax("expected a struct variant"))
Err(Error::type_mismatch(Type::StructVariant))
}
}

View File

@ -261,7 +261,7 @@ impl<I, T> de::SeqVisitor for SeqDeserializer<I>
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream())
Err(de::Error::length_mismatch(self.len))
}
}
@ -382,7 +382,7 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream())
Err(de::Error::length_mismatch(self.len))
}
}

View File

@ -843,7 +843,7 @@ impl<'a> de::SeqVisitor for SeqDeserializer<'a> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream())
Err(de::Error::length_mismatch(self.len))
}
}
@ -888,7 +888,7 @@ impl<'a> de::MapVisitor for MapDeserializer<'a> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream())
Err(de::Error::length_mismatch(self.len))
}
}