Merge pull request #134 from erickt/err
Add Error::length_mismatch, Error::type_mismatch, and de::Type
This commit is contained in:
commit
c5541cddeb
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user