Fix an error message test, simlify some serde code
This commit is contained in:
parent
d02e622330
commit
3345fea319
|
@ -57,6 +57,8 @@ pub enum DecodeErrorKind {
|
||||||
CustomError(String),
|
CustomError(String),
|
||||||
/// The end of the TOML input was reached too soon
|
/// The end of the TOML input was reached too soon
|
||||||
EndOfStream,
|
EndOfStream,
|
||||||
|
/// Produced by serde ...
|
||||||
|
InvalidType(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a TOML value into a decodable type.
|
/// Decodes a TOML value into a decodable type.
|
||||||
|
@ -197,6 +199,9 @@ impl fmt::Display for DecodeError {
|
||||||
EndOfStream => {
|
EndOfStream => {
|
||||||
write!(f, "end of stream")
|
write!(f, "end of stream")
|
||||||
}
|
}
|
||||||
|
InvalidType(s) => {
|
||||||
|
write!(f, "invalid type: {}", s)
|
||||||
|
}
|
||||||
CustomError(ref s) => {
|
CustomError(ref s) => {
|
||||||
write!(f, "custom error: {}", s)
|
write!(f, "custom error: {}", s)
|
||||||
}
|
}
|
||||||
|
@ -223,6 +228,7 @@ impl error::Error for DecodeError {
|
||||||
NilTooLong => "nonzero length string representing nil",
|
NilTooLong => "nonzero length string representing nil",
|
||||||
SyntaxError => "syntax error",
|
SyntaxError => "syntax error",
|
||||||
EndOfStream => "end of stream",
|
EndOfStream => "end of stream",
|
||||||
|
InvalidType(..) => "invalid type",
|
||||||
CustomError(..) => "custom error",
|
CustomError(..) => "custom error",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,29 +3,6 @@ use Value;
|
||||||
use super::{Decoder, DecodeError, DecodeErrorKind};
|
use super::{Decoder, DecodeError, DecodeErrorKind};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
|
|
||||||
match err {
|
|
||||||
de::value::Error::Custom(s) => de::Error::custom(s),
|
|
||||||
de::value::Error::EndOfStream => de::Error::end_of_stream(),
|
|
||||||
de::value::Error::MissingField(s) => {
|
|
||||||
DecodeError {
|
|
||||||
field: Some(s.to_string()),
|
|
||||||
kind: DecodeErrorKind::ExpectedField(Some(ty)),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
de::value::Error::UnknownField(s) => {
|
|
||||||
DecodeError {
|
|
||||||
field: Some(s.to_string()),
|
|
||||||
kind: DecodeErrorKind::UnknownField,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
de::value::Error::InvalidType(ty) => de::Error::invalid_type(ty),
|
|
||||||
de::value::Error::InvalidLength(l) => de::Error::invalid_length(l),
|
|
||||||
de::value::Error::InvalidValue(v) => de::Error::invalid_value(&v),
|
|
||||||
de::value::Error::UnknownVariant(v) => de::Error::unknown_variant(&v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl de::Deserializer for Decoder {
|
impl de::Deserializer for Decoder {
|
||||||
type Error = DecodeError;
|
type Error = DecodeError;
|
||||||
|
|
||||||
|
@ -34,21 +11,11 @@ impl de::Deserializer for Decoder {
|
||||||
where V: de::Visitor
|
where V: de::Visitor
|
||||||
{
|
{
|
||||||
match self.toml.take() {
|
match self.toml.take() {
|
||||||
Some(Value::String(s)) => {
|
Some(Value::String(s)) => visitor.visit_string(s),
|
||||||
visitor.visit_string(s).map_err(|e| se2toml(e, "string"))
|
Some(Value::Integer(i)) => visitor.visit_i64(i),
|
||||||
}
|
Some(Value::Float(f)) => visitor.visit_f64(f),
|
||||||
Some(Value::Integer(i)) => {
|
Some(Value::Boolean(b)) => visitor.visit_bool(b),
|
||||||
visitor.visit_i64(i).map_err(|e| se2toml(e, "integer"))
|
Some(Value::Datetime(s)) => visitor.visit_string(s),
|
||||||
}
|
|
||||||
Some(Value::Float(f)) => {
|
|
||||||
visitor.visit_f64(f).map_err(|e| se2toml(e, "float"))
|
|
||||||
}
|
|
||||||
Some(Value::Boolean(b)) => {
|
|
||||||
visitor.visit_bool(b).map_err(|e| se2toml(e, "bool"))
|
|
||||||
}
|
|
||||||
Some(Value::Datetime(s)) => {
|
|
||||||
visitor.visit_string(s).map_err(|e| se2toml(e, "date"))
|
|
||||||
}
|
|
||||||
Some(Value::Array(a)) => {
|
Some(Value::Array(a)) => {
|
||||||
let len = a.len();
|
let len = a.len();
|
||||||
let iter = a.into_iter();
|
let iter = a.into_iter();
|
||||||
|
@ -62,34 +29,18 @@ impl de::Deserializer for Decoder {
|
||||||
value: None,
|
value: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
None => Err(de::Error::end_of_stream()),
|
None => Err(self.err(DecodeErrorKind::EndOfStream)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_isize<V>(&mut self, visitor: V)
|
fn deserialize_bool<V>(&mut self, mut visitor: V)
|
||||||
-> Result<V::Value, DecodeError>
|
-> Result<V::Value, DecodeError>
|
||||||
where V: de::Visitor
|
where V: de::Visitor
|
||||||
{
|
{
|
||||||
self.deserialize_i64(visitor)
|
match self.toml.take() {
|
||||||
|
Some(Value::Boolean(b)) => visitor.visit_bool(b),
|
||||||
|
ref found => Err(self.mismatch("bool", found)),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_i8<V>(&mut self, visitor: V) -> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_i64(visitor)
|
|
||||||
}
|
|
||||||
fn deserialize_i16<V>(&mut self, visitor: V)
|
|
||||||
-> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_i64(visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_i32<V>(&mut self, visitor: V)
|
|
||||||
-> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_i64(visitor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_i64<V>(&mut self, mut visitor: V)
|
fn deserialize_i64<V>(&mut self, mut visitor: V)
|
||||||
|
@ -97,50 +48,15 @@ impl de::Deserializer for Decoder {
|
||||||
where V: de::Visitor
|
where V: de::Visitor
|
||||||
{
|
{
|
||||||
match self.toml.take() {
|
match self.toml.take() {
|
||||||
Some(Value::Integer(f)) => {
|
Some(Value::Integer(f)) => visitor.visit_i64(f),
|
||||||
visitor.visit_i64(f).map_err(|e| se2toml(e, "integer"))
|
|
||||||
}
|
|
||||||
ref found => Err(self.mismatch("integer", found)),
|
ref found => Err(self.mismatch("integer", found)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_usize<V>(&mut self, visitor: V)
|
fn deserialize_u64<V>(&mut self, v: V) -> Result<V::Value, DecodeError>
|
||||||
-> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
where V: de::Visitor
|
||||||
{
|
{
|
||||||
self.deserialize_i64(visitor)
|
self.deserialize_i64(v)
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_u8<V>(&mut self, visitor: V) -> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_i64(visitor)
|
|
||||||
}
|
|
||||||
fn deserialize_u16<V>(&mut self, visitor: V) -> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_i64(visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_u32<V>(&mut self, visitor: V)
|
|
||||||
-> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_i64(visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_u64<V>(&mut self, visitor: V)
|
|
||||||
-> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_i64(visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_f32<V>(&mut self, visitor: V)
|
|
||||||
-> Result<V::Value, DecodeError>
|
|
||||||
where V: de::Visitor
|
|
||||||
{
|
|
||||||
self.deserialize_f64(visitor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_f64<V>(&mut self, mut visitor: V)
|
fn deserialize_f64<V>(&mut self, mut visitor: V)
|
||||||
|
@ -148,13 +64,33 @@ impl de::Deserializer for Decoder {
|
||||||
where V: de::Visitor
|
where V: de::Visitor
|
||||||
{
|
{
|
||||||
match self.toml.take() {
|
match self.toml.take() {
|
||||||
Some(Value::Float(f)) => {
|
Some(Value::Float(f)) => visitor.visit_f64(f),
|
||||||
visitor.visit_f64(f).map_err(|e| se2toml(e, "float"))
|
|
||||||
}
|
|
||||||
ref found => Err(self.mismatch("float", found)),
|
ref found => Err(self.mismatch("float", found)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_str<V>(&mut self, mut visitor: V)
|
||||||
|
-> Result<V::Value, Self::Error>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
match self.toml.take() {
|
||||||
|
Some(Value::String(s)) => visitor.visit_string(s),
|
||||||
|
ref found => Err(self.mismatch("string", found)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_char<V>(&mut self, mut visitor: V)
|
||||||
|
-> Result<V::Value, DecodeError>
|
||||||
|
where V: de::Visitor
|
||||||
|
{
|
||||||
|
match self.toml.take() {
|
||||||
|
Some(Value::String(ref s)) if s.chars().count() == 1 => {
|
||||||
|
visitor.visit_char(s.chars().next().unwrap())
|
||||||
|
}
|
||||||
|
ref found => return Err(self.mismatch("string", found)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_option<V>(&mut self, mut visitor: V)
|
fn deserialize_option<V>(&mut self, mut visitor: V)
|
||||||
-> Result<V::Value, DecodeError>
|
-> Result<V::Value, DecodeError>
|
||||||
where V: de::Visitor
|
where V: de::Visitor
|
||||||
|
@ -172,13 +108,29 @@ impl de::Deserializer for Decoder {
|
||||||
{
|
{
|
||||||
if self.toml.is_none() {
|
if self.toml.is_none() {
|
||||||
let iter = None::<i32>.into_iter();
|
let iter = None::<i32>.into_iter();
|
||||||
let e = visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0));
|
visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0))
|
||||||
e.map_err(|e| se2toml(e, "array"))
|
|
||||||
} else {
|
} else {
|
||||||
self.deserialize(visitor)
|
self.deserialize(visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_map<V>(&mut self, mut visitor: V)
|
||||||
|
-> Result<V::Value, DecodeError>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
match self.toml.take() {
|
||||||
|
Some(Value::Table(t)) => {
|
||||||
|
visitor.visit_map(MapVisitor {
|
||||||
|
iter: t.into_iter(),
|
||||||
|
de: self,
|
||||||
|
key: None,
|
||||||
|
value: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ref found => Err(self.mismatch("table", found)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_enum<V>(&mut self,
|
fn deserialize_enum<V>(&mut self,
|
||||||
_enum: &str,
|
_enum: &str,
|
||||||
variants: &[&str],
|
variants: &[&str],
|
||||||
|
@ -238,7 +190,7 @@ impl de::VariantVisitor for VariantVisitor {
|
||||||
|
|
||||||
let mut de = self.variant.into_deserializer();
|
let mut de = self.variant.into_deserializer();
|
||||||
|
|
||||||
de::Deserialize::deserialize(&mut de).map_err(|e| se2toml(e, "variant"))
|
de::Deserialize::deserialize(&mut de)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_unit(&mut self) -> Result<(), DecodeError> {
|
fn visit_unit(&mut self) -> Result<(), DecodeError> {
|
||||||
|
@ -364,6 +316,45 @@ impl de::Error for DecodeError {
|
||||||
kind: DecodeErrorKind::UnknownField,
|
kind: DecodeErrorKind::UnknownField,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn invalid_type(ty: de::Type) -> Self {
|
||||||
|
DecodeError {
|
||||||
|
field: None,
|
||||||
|
kind: DecodeErrorKind::InvalidType(match ty {
|
||||||
|
de::Type::Bool => "bool",
|
||||||
|
de::Type::Usize |
|
||||||
|
de::Type::U8 |
|
||||||
|
de::Type::U16 |
|
||||||
|
de::Type::U32 |
|
||||||
|
de::Type::U64 |
|
||||||
|
de::Type::Isize |
|
||||||
|
de::Type::I8 |
|
||||||
|
de::Type::I16 |
|
||||||
|
de::Type::I32 |
|
||||||
|
de::Type::I64 => "integer",
|
||||||
|
de::Type::F32 |
|
||||||
|
de::Type::F64 => "float",
|
||||||
|
de::Type::Char |
|
||||||
|
de::Type::Str |
|
||||||
|
de::Type::String => "string",
|
||||||
|
de::Type::Seq => "array",
|
||||||
|
de::Type::Struct |
|
||||||
|
de::Type::Map => "table",
|
||||||
|
de::Type::Unit => "Unit",
|
||||||
|
de::Type::Option => "Option",
|
||||||
|
de::Type::UnitStruct => "UnitStruct",
|
||||||
|
de::Type::NewtypeStruct => "NewtypeStruct",
|
||||||
|
de::Type::TupleStruct => "TupleStruct",
|
||||||
|
de::Type::FieldName => "FieldName",
|
||||||
|
de::Type::Tuple => "Tuple",
|
||||||
|
de::Type::Enum => "Enum",
|
||||||
|
de::Type::VariantName => "VariantName",
|
||||||
|
de::Type::StructVariant => "StructVariant",
|
||||||
|
de::Type::TupleVariant => "TupleVariant",
|
||||||
|
de::Type::UnitVariant => "UnitVariant",
|
||||||
|
de::Type::Bytes => "Bytes",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MapVisitor<'a, I> {
|
struct MapVisitor<'a, I> {
|
||||||
|
@ -444,6 +435,13 @@ impl<'a, I> de::MapVisitor for MapVisitor<'a, I>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(&mut self) -> Result<(), DecodeError> {
|
fn end(&mut self) -> Result<(), DecodeError> {
|
||||||
|
if let Some(v) = self.value.take() {
|
||||||
|
self.put_value_back(v);
|
||||||
|
}
|
||||||
|
while let Some((k, v)) = self.iter.next() {
|
||||||
|
self.key = Some(k);
|
||||||
|
self.put_value_back(v);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +450,7 @@ impl<'a, I> de::MapVisitor for MapVisitor<'a, I>
|
||||||
// See if the type can deserialize from a unit.
|
// See if the type can deserialize from a unit.
|
||||||
match de::Deserialize::deserialize(&mut UnitDeserializer) {
|
match de::Deserialize::deserialize(&mut UnitDeserializer) {
|
||||||
Err(DecodeError {
|
Err(DecodeError {
|
||||||
kind: DecodeErrorKind::SyntaxError,
|
kind: DecodeErrorKind::InvalidType(..),
|
||||||
field,
|
field,
|
||||||
}) => Err(DecodeError {
|
}) => Err(DecodeError {
|
||||||
field: field.or(Some(field_name.to_string())),
|
field: field.or(Some(field_name.to_string())),
|
||||||
|
|
Loading…
Reference in a new issue