diff options
-rw-r--r-- | src/decoder/mod.rs | 6 | ||||
-rw-r--r-- | src/decoder/serde.rs | 198 |
2 files changed, 104 insertions, 100 deletions
diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 6180c13..a596280 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -57,6 +57,8 @@ pub enum DecodeErrorKind { CustomError(String), /// The end of the TOML input was reached too soon EndOfStream, + /// Produced by serde ... + InvalidType(&'static str), } /// Decodes a TOML value into a decodable type. @@ -197,6 +199,9 @@ impl fmt::Display for DecodeError { EndOfStream => { write!(f, "end of stream") } + InvalidType(s) => { + write!(f, "invalid type: {}", s) + } CustomError(ref s) => { write!(f, "custom error: {}", s) } @@ -223,6 +228,7 @@ impl error::Error for DecodeError { NilTooLong => "nonzero length string representing nil", SyntaxError => "syntax error", EndOfStream => "end of stream", + InvalidType(..) => "invalid type", CustomError(..) => "custom error", } } diff --git a/src/decoder/serde.rs b/src/decoder/serde.rs index 493b8fd..099a65b 100644 --- a/src/decoder/serde.rs +++ b/src/decoder/serde.rs @@ -3,29 +3,6 @@ use Value; use super::{Decoder, DecodeError, DecodeErrorKind}; 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 { type Error = DecodeError; @@ -34,21 +11,11 @@ impl de::Deserializer for Decoder { where V: de::Visitor { match self.toml.take() { - Some(Value::String(s)) => { - visitor.visit_string(s).map_err(|e| se2toml(e, "string")) - } - Some(Value::Integer(i)) => { - visitor.visit_i64(i).map_err(|e| se2toml(e, "integer")) - } - 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::String(s)) => visitor.visit_string(s), + Some(Value::Integer(i)) => visitor.visit_i64(i), + Some(Value::Float(f)) => visitor.visit_f64(f), + Some(Value::Boolean(b)) => visitor.visit_bool(b), + Some(Value::Datetime(s)) => visitor.visit_string(s), Some(Value::Array(a)) => { let len = a.len(); let iter = a.into_iter(); @@ -62,34 +29,18 @@ impl de::Deserializer for Decoder { value: None, }) } - None => Err(de::Error::end_of_stream()), + None => Err(self.err(DecodeErrorKind::EndOfStream)), } } - fn deserialize_isize<V>(&mut self, visitor: V) - -> Result<V::Value, DecodeError> + fn deserialize_bool<V>(&mut self, mut visitor: V) + -> Result<V::Value, DecodeError> where V: de::Visitor { - self.deserialize_i64(visitor) - } - - 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) + match self.toml.take() { + Some(Value::Boolean(b)) => visitor.visit_bool(b), + ref found => Err(self.mismatch("bool", found)), + } } fn deserialize_i64<V>(&mut self, mut visitor: V) @@ -97,61 +48,46 @@ impl de::Deserializer for Decoder { where V: de::Visitor { match self.toml.take() { - Some(Value::Integer(f)) => { - visitor.visit_i64(f).map_err(|e| se2toml(e, "integer")) - } + Some(Value::Integer(f)) => visitor.visit_i64(f), ref found => Err(self.mismatch("integer", found)), } } - fn deserialize_usize<V>(&mut self, visitor: V) - -> Result<V::Value, DecodeError> - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - 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> + fn deserialize_u64<V>(&mut self, v: V) -> Result<V::Value, DecodeError> where V: de::Visitor { - self.deserialize_i64(visitor) + self.deserialize_i64(v) } - 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) + fn deserialize_f64<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError> where V: de::Visitor { - self.deserialize_i64(visitor) + match self.toml.take() { + Some(Value::Float(f)) => visitor.visit_f64(f), + ref found => Err(self.mismatch("float", found)), + } } - fn deserialize_f32<V>(&mut self, visitor: V) - -> Result<V::Value, DecodeError> - where V: de::Visitor + fn deserialize_str<V>(&mut self, mut visitor: V) + -> Result<V::Value, Self::Error> + where V: de::Visitor, { - self.deserialize_f64(visitor) + match self.toml.take() { + Some(Value::String(s)) => visitor.visit_string(s), + ref found => Err(self.mismatch("string", found)), + } } - fn deserialize_f64<V>(&mut self, mut visitor: V) - -> Result<V::Value, DecodeError> + fn deserialize_char<V>(&mut self, mut visitor: V) + -> Result<V::Value, DecodeError> where V: de::Visitor { match self.toml.take() { - Some(Value::Float(f)) => { - visitor.visit_f64(f).map_err(|e| se2toml(e, "float")) + Some(Value::String(ref s)) if s.chars().count() == 1 => { + visitor.visit_char(s.chars().next().unwrap()) } - ref found => Err(self.mismatch("float", found)), + ref found => return Err(self.mismatch("string", found)), } } @@ -172,13 +108,29 @@ impl de::Deserializer for Decoder { { if self.toml.is_none() { let iter = None::<i32>.into_iter(); - let e = visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0)); - e.map_err(|e| se2toml(e, "array")) + visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0)) } else { 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, _enum: &str, variants: &[&str], @@ -238,7 +190,7 @@ impl de::VariantVisitor for VariantVisitor { 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> { @@ -364,6 +316,45 @@ impl de::Error for DecodeError { 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> { @@ -444,6 +435,13 @@ impl<'a, I> de::MapVisitor for MapVisitor<'a, I> } 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(()) } @@ -452,7 +450,7 @@ impl<'a, I> de::MapVisitor for MapVisitor<'a, I> // See if the type can deserialize from a unit. match de::Deserialize::deserialize(&mut UnitDeserializer) { Err(DecodeError { - kind: DecodeErrorKind::SyntaxError, + kind: DecodeErrorKind::InvalidType(..), field, }) => Err(DecodeError { field: field.or(Some(field_name.to_string())), |