From f66d8bcf33530c858a502bfa170f2383a8cbc204 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 29 Jan 2017 16:53:20 -0800 Subject: Rewrite crate with serde support from ground up This commit completely rewrites this crate from the ground up, supporting serde at the lowest levels as I believe serde support was intended to do. This is a major change from the previous versions of this crate, with a summary of changes being: * Serialization directly to TOML is now supported without going through a `Value` first. * Deserialization directly from TOML is now supported without going through a `Value`. Note that due to the TOML format some values still are buffered in intermediate memory, but overall this should be at a minimum now. * The API of `Value` was overhauled to match the API of `serde_json::Value`. The changes here were to: * Add `is_*` accessors * Add `get` and `get_mut` for one-field lookups. * Implement panicking lookups through `Index` The old `index` methods are now gone in favor of `get` and `Index` implementations. * A `Datetime` type has been added to represent a TOML datetime in a first-class fashion. Currently this type provides no accessors other than a `Display` implementation, but the idea is that this will grow support over time for decomposing the date. * Support for the `rustc-serialize` crate has been dropped, that'll stay on the 0.2 and 0.1 release trains. * This crate no longer supports the detection of unused fields, for that though you can use the `serde_ignored` crate on crates.io --- src/decoder/mod.rs | 240 ------------- src/decoder/rustc_serialize.rs | 371 -------------------- src/decoder/serde.rs | 773 ----------------------------------------- 3 files changed, 1384 deletions(-) delete mode 100644 src/decoder/mod.rs delete mode 100644 src/decoder/rustc_serialize.rs delete mode 100644 src/decoder/serde.rs (limited to 'src/decoder') diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs deleted file mode 100644 index 51a9ea2..0000000 --- a/src/decoder/mod.rs +++ /dev/null @@ -1,240 +0,0 @@ -use std::error; -use std::fmt; - -use std::collections::{btree_map, BTreeMap}; -use std::iter::Peekable; - -use Value; -use self::DecodeErrorKind::*; - -#[cfg(feature = "rustc-serialize")] mod rustc_serialize; -#[cfg(feature = "serde")] mod serde; - -/// A structure to transform TOML values into Rust values. -/// -/// This decoder implements the serialization `Decoder` interface, allowing -/// `Decodable` types to be generated by this decoder. The input is any -/// arbitrary TOML value. -pub struct Decoder { - /// The TOML value left over after decoding. This can be used to inspect - /// whether fields were decoded or not. - pub toml: Option, - cur_field: Option, - - // These aren't used if serde is in use - #[cfg_attr(feature = "serde", allow(dead_code))] - cur_map: Peekable>, - #[cfg_attr(feature = "serde", allow(dead_code))] - leftover_map: ::Table, -} - -/// Description for errors which can occur while decoding a type. -#[derive(PartialEq, Debug)] -pub struct DecodeError { - /// Field that this error applies to. - pub field: Option, - /// The type of error which occurred while decoding, - pub kind: DecodeErrorKind, -} - -/// Enumeration of possible errors which can occur while decoding a structure. -#[derive(PartialEq, Debug)] -pub enum DecodeErrorKind { - /// An error flagged by the application, e.g. value out of range - ApplicationError(String), - /// A field was expected, but none was found. - ExpectedField(/* type */ Option<&'static str>), - /// A field was found, but it was not an expected one. - UnknownField, - /// A field was found, but it had the wrong type. - ExpectedType(/* expected */ &'static str, /* found */ &'static str), - /// The nth map key was expected, but none was found. - ExpectedMapKey(usize), - /// The nth map element was expected, but none was found. - ExpectedMapElement(usize), - /// An enum decoding was requested, but no variants were supplied - NoEnumVariants, - /// The unit type was being decoded, but a non-zero length string was found - NilTooLong, - /// There was an error with the syntactical structure of the TOML. - SyntaxError, - /// A custom error was generated when decoding. - 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. -/// -/// This function will consume the given TOML value and attempt to decode it -/// into the type specified. If decoding fails, `None` will be returned. If a -/// finer-grained error is desired, then it is recommended to use `Decodable` -/// directly. -#[cfg(feature = "rustc-serialize")] -pub fn decode(toml: Value) -> Option { - ::rustc_serialize::Decodable::decode(&mut Decoder::new(toml)).ok() -} - -/// Decodes a TOML value into a decodable type. -/// -/// This function will consume the given TOML value and attempt to decode it -/// into the type specified. If decoding fails, `None` will be returned. If a -/// finer-grained error is desired, then it is recommended to use `Decodable` -/// directly. -#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))] -pub fn decode(toml: Value) -> Option { - ::serde::Deserialize::deserialize(&mut Decoder::new(toml)).ok() -} - -/// Decodes a string into a toml-encoded value. -/// -/// This function will parse the given string into a TOML value, and then parse -/// the TOML value into the desired type. If any error occurs, `None` is -/// returned. -/// -/// If more fine-grained errors are desired, these steps should be driven -/// manually. -#[cfg(feature = "rustc-serialize")] -pub fn decode_str(s: &str) -> Option { - ::Parser::new(s).parse().and_then(|t| decode(Value::Table(t))) -} - -/// Decodes a string into a toml-encoded value. -/// -/// This function will parse the given string into a TOML value, and then parse -/// the TOML value into the desired type. If any error occurs, `None` is -/// returned. -/// -/// If more fine-grained errors are desired, these steps should be driven -/// manually. -#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))] -pub fn decode_str(s: &str) -> Option { - ::Parser::new(s).parse().and_then(|t| decode(Value::Table(t))) -} - -impl Decoder { - /// Creates a new decoder, consuming the TOML value to decode. - /// - /// This decoder can be passed to the `Decodable` methods or driven - /// manually. - pub fn new(toml: Value) -> Decoder { - Decoder::new_empty(Some(toml), None) - } - - fn sub_decoder(&self, toml: Option, field: &str) -> Decoder { - let cur_field = if field.is_empty() { - self.cur_field.clone() - } else { - match self.cur_field { - None => Some(field.to_string()), - Some(ref s) => Some(format!("{}.{}", s, field)) - } - }; - Decoder::new_empty(toml, cur_field) - } - - fn new_empty(toml: Option, cur_field: Option) -> Decoder { - Decoder { - toml: toml, - cur_field: cur_field, - leftover_map: BTreeMap::new(), - cur_map: BTreeMap::new().into_iter().peekable(), - } - } - - fn err(&self, kind: DecodeErrorKind) -> DecodeError { - DecodeError { - field: self.cur_field.clone(), - kind: kind, - } - } - - fn mismatch(&self, expected: &'static str, - found: &Option) -> DecodeError{ - match *found { - Some(ref val) => self.err(ExpectedType(expected, val.type_str())), - None => self.err(ExpectedField(Some(expected))), - } - } -} - -impl fmt::Display for DecodeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(match self.kind { - ApplicationError(ref err) => { - write!(f, "{}", err) - } - ExpectedField(expected_type) => { - match expected_type { - Some("table") => write!(f, "expected a section"), - Some(e) => write!(f, "expected a value of type `{}`", e), - None => write!(f, "expected a value"), - } - } - UnknownField => write!(f, "unknown field"), - ExpectedType(expected, found) => { - fn humanize(s: &str) -> String { - if s == "section" { - "a section".to_string() - } else { - format!("a value of type `{}`", s) - } - } - write!(f, "expected {}, but found {}", - humanize(expected), - humanize(found)) - } - ExpectedMapKey(idx) => { - write!(f, "expected at least {} keys", idx + 1) - } - ExpectedMapElement(idx) => { - write!(f, "expected at least {} elements", idx + 1) - } - NoEnumVariants => { - write!(f, "expected an enum variant to decode to") - } - NilTooLong => { - write!(f, "expected 0-length string") - } - SyntaxError => { - write!(f, "syntax error") - } - EndOfStream => { - write!(f, "end of stream") - } - InvalidType(s) => { - write!(f, "invalid type: {}", s) - } - CustomError(ref s) => { - write!(f, "custom error: {}", s) - } - }); - match self.field { - Some(ref s) => { - write!(f, " for the key `{}`", s) - } - None => Ok(()) - } - } -} - -impl error::Error for DecodeError { - fn description(&self) -> &str { - match self.kind { - ApplicationError(ref s) => &**s, - ExpectedField(..) => "expected a field", - UnknownField => "found an unknown field", - ExpectedType(..) => "expected a type", - ExpectedMapKey(..) => "expected a map key", - ExpectedMapElement(..) => "expected a map element", - NoEnumVariants => "no enum variants to decode to", - NilTooLong => "nonzero length string representing nil", - SyntaxError => "syntax error", - EndOfStream => "end of stream", - InvalidType(..) => "invalid type", - CustomError(..) => "custom error", - } - } -} diff --git a/src/decoder/rustc_serialize.rs b/src/decoder/rustc_serialize.rs deleted file mode 100644 index f850663..0000000 --- a/src/decoder/rustc_serialize.rs +++ /dev/null @@ -1,371 +0,0 @@ -use rustc_serialize; -use std::mem; -use std::collections::BTreeMap; - -use super::{Decoder, DecodeError}; -use super::DecodeErrorKind::*; -use Value; - -impl rustc_serialize::Decoder for Decoder { - type Error = DecodeError; - fn read_nil(&mut self) -> Result<(), DecodeError> { - match self.toml { - Some(Value::String(ref s)) if s.is_empty() => {} - Some(Value::String(..)) => return Err(self.err(NilTooLong)), - ref found => return Err(self.mismatch("string", found)), - } - self.toml.take(); - Ok(()) - } - fn read_usize(&mut self) -> Result { - self.read_i64().map(|i| i as usize) - } - fn read_u64(&mut self) -> Result { - self.read_i64().map(|i| i as u64) - } - fn read_u32(&mut self) -> Result { - self.read_i64().map(|i| i as u32) - } - fn read_u16(&mut self) -> Result { - self.read_i64().map(|i| i as u16) - } - fn read_u8(&mut self) -> Result { - self.read_i64().map(|i| i as u8) - } - fn read_isize(&mut self) -> Result { - self.read_i64().map(|i| i as isize) - } - fn read_i64(&mut self) -> Result { - match self.toml { - Some(Value::Integer(i)) => { self.toml.take(); Ok(i) } - ref found => Err(self.mismatch("integer", found)), - } - } - fn read_i32(&mut self) -> Result { - self.read_i64().map(|i| i as i32) - } - fn read_i16(&mut self) -> Result { - self.read_i64().map(|i| i as i16) - } - fn read_i8(&mut self) -> Result { - self.read_i64().map(|i| i as i8) - } - fn read_bool(&mut self) -> Result { - match self.toml { - Some(Value::Boolean(b)) => { self.toml.take(); Ok(b) } - ref found => Err(self.mismatch("bool", found)), - } - } - fn read_f64(&mut self) -> Result { - match self.toml { - Some(Value::Float(f)) => { self.toml.take(); Ok(f) }, - ref found => Err(self.mismatch("float", found)), - } - } - fn read_f32(&mut self) -> Result { - self.read_f64().map(|f| f as f32) - } - fn read_char(&mut self) -> Result { - let ch = match self.toml { - Some(Value::String(ref s)) if s.chars().count() == 1 => - s.chars().next().unwrap(), - ref found => return Err(self.mismatch("string", found)), - }; - self.toml.take(); - Ok(ch) - } - fn read_str(&mut self) -> Result { - match self.toml.take() { - Some(Value::String(s)) => Ok(s), - found => { - let err = Err(self.mismatch("string", &found)); - self.toml = found; - err - } - } - } - - // Compound types: - fn read_enum(&mut self, _name: &str, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - f(self) - } - - fn read_enum_variant(&mut self, names: &[&str], mut f: F) - -> Result - where F: FnMut(&mut Decoder, usize) -> Result - { - // When decoding enums, this crate takes the strategy of trying to - // decode the current TOML as all of the possible variants, returning - // success on the first one that succeeds. - // - // Note that fidelity of the errors returned here is a little nebulous, - // but we try to return the error that had the relevant field as the - // longest field. This way we hopefully match an error against what was - // most likely being written down without losing too much info. - let mut first_error = None::; - for i in 0..names.len() { - let mut d = self.sub_decoder(self.toml.clone(), ""); - match f(&mut d, i) { - Ok(t) => { - self.toml = d.toml; - return Ok(t) - } - Err(e) => { - if let Some(ref first) = first_error { - let my_len = e.field.as_ref().map(|s| s.len()); - let first_len = first.field.as_ref().map(|s| s.len()); - if my_len <= first_len { - continue - } - } - first_error = Some(e); - } - } - } - Err(first_error.unwrap_or_else(|| self.err(NoEnumVariants))) - } - fn read_enum_variant_arg(&mut self, _a_idx: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - f(self) - } - - fn read_enum_struct_variant(&mut self, _names: &[&str], _f: F) - -> Result - where F: FnMut(&mut Decoder, usize) -> Result - { - panic!() - } - fn read_enum_struct_variant_field(&mut self, - _f_name: &str, - _f_idx: usize, - _f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - panic!() - } - - fn read_struct(&mut self, _s_name: &str, _len: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - match self.toml { - Some(Value::Table(..)) => { - let ret = try!(f(self)); - match self.toml { - Some(Value::Table(ref t)) if t.is_empty() => {} - _ => return Ok(ret) - } - self.toml.take(); - Ok(ret) - } - ref found => Err(self.mismatch("table", found)), - } - } - fn read_struct_field(&mut self, f_name: &str, _f_idx: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - let field = f_name.to_string(); - let toml = match self.toml { - Some(Value::Table(ref mut table)) => { - table.remove(&field) - .or_else(|| table.remove(&f_name.replace("_", "-"))) - }, - ref found => return Err(self.mismatch("table", found)), - }; - let mut d = self.sub_decoder(toml, f_name); - let ret = try!(f(&mut d)); - if let Some(value) = d.toml { - if let Some(Value::Table(ref mut table)) = self.toml { - table.insert(field, value); - } - } - Ok(ret) - } - - fn read_tuple(&mut self, tuple_len: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - self.read_seq(move |d, len| { - assert!(len == tuple_len, - "expected tuple of length `{}`, found tuple \ - of length `{}`", tuple_len, len); - f(d) - }) - } - fn read_tuple_arg(&mut self, a_idx: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - self.read_seq_elt(a_idx, f) - } - - fn read_tuple_struct(&mut self, _s_name: &str, _len: usize, _f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - panic!() - } - fn read_tuple_struct_arg(&mut self, _a_idx: usize, _f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - panic!() - } - - // Specialized types: - fn read_option(&mut self, mut f: F) - -> Result - where F: FnMut(&mut Decoder, bool) -> Result - { - match self.toml { - Some(..) => f(self, true), - None => f(self, false), - } - } - - fn read_seq(&mut self, f: F) -> Result - where F: FnOnce(&mut Decoder, usize) -> Result - { - let len = match self.toml { - Some(Value::Array(ref arr)) => arr.len(), - None => 0, - ref found => return Err(self.mismatch("array", found)), - }; - let ret = try!(f(self, len)); - match self.toml { - Some(Value::Array(ref mut arr)) => { - arr.retain(|slot| slot.as_integer() != Some(0)); - if !arr.is_empty() { return Ok(ret) } - } - _ => return Ok(ret) - } - self.toml.take(); - Ok(ret) - } - fn read_seq_elt(&mut self, idx: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - let toml = match self.toml { - Some(Value::Array(ref mut arr)) => { - mem::replace(&mut arr[idx], Value::Integer(0)) - } - ref found => return Err(self.mismatch("array", found)), - }; - let mut d = self.sub_decoder(Some(toml), ""); - let ret = try!(f(&mut d)); - if let Some(toml) = d.toml { - if let Some(Value::Array(ref mut arr)) = self.toml { - arr[idx] = toml; - } - } - Ok(ret) - } - - fn read_map(&mut self, f: F) - -> Result - where F: FnOnce(&mut Decoder, usize) -> Result - { - let map = match self.toml.take() { - Some(Value::Table(table)) => table, - found => { - self.toml = found; - return Err(self.mismatch("table", &self.toml)) - } - }; - let amt = map.len(); - let prev_iter = mem::replace(&mut self.cur_map, - map.into_iter().peekable()); - let prev_map = mem::replace(&mut self.leftover_map, BTreeMap::new()); - let ret = try!(f(self, amt)); - let leftover = mem::replace(&mut self.leftover_map, prev_map); - self.cur_map = prev_iter; - if !leftover.is_empty() { - self.toml = Some(Value::Table(leftover)); - } - Ok(ret) - } - fn read_map_elt_key(&mut self, idx: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - let key = match self.cur_map.peek().map(|p| p.0.clone()) { - Some(k) => k, - None => return Err(self.err(ExpectedMapKey(idx))), - }; - let val = Value::String(key.clone()); - f(&mut self.sub_decoder(Some(val), &key)) - } - fn read_map_elt_val(&mut self, idx: usize, f: F) - -> Result - where F: FnOnce(&mut Decoder) -> Result - { - match self.cur_map.next() { - Some((key, value)) => { - let mut d = self.sub_decoder(Some(value), &key); - let ret = f(&mut d); - if let Some(toml) = d.toml.take() { - self.leftover_map.insert(key, toml); - } - ret - } - None => Err(self.err(ExpectedMapElement(idx))), - } - } - - fn error(&mut self, err: &str) -> DecodeError { - DecodeError { - field: self.cur_field.clone(), - kind: ApplicationError(err.to_string()) - } - } -} - -#[cfg(test)] -mod tests { - use rustc_serialize::Decodable; - use std::collections::HashMap; - - use {Parser, Decoder, Value}; - - #[test] - fn bad_enum_chooses_longest_error() { - #[derive(RustcDecodable)] - #[allow(dead_code)] - struct Foo { - wut: HashMap, - } - - #[derive(RustcDecodable)] - enum Bar { - Simple(String), - Detailed(Baz), - } - - #[derive(RustcDecodable, Debug)] - struct Baz { - features: Vec, - } - - let s = r#" - [wut] - a = { features = "" } - "#; - let v = Parser::new(s).parse().unwrap(); - let mut d = Decoder::new(Value::Table(v)); - let err = match Foo::decode(&mut d) { - Ok(_) => panic!("expected error"), - Err(e) => e, - }; - assert_eq!(err.field.as_ref().unwrap(), "wut.a.features"); - - } -} diff --git a/src/decoder/serde.rs b/src/decoder/serde.rs deleted file mode 100644 index 81a2bae..0000000 --- a/src/decoder/serde.rs +++ /dev/null @@ -1,773 +0,0 @@ -use serde::de; -use Value; -use super::{Decoder, DecodeError, DecodeErrorKind}; -use std::collections::BTreeMap; - -macro_rules! forward_to_deserialize { - ($( - $name:ident ( $( $arg:ident : $ty:ty ),* ); - )*) => { - $( - forward_to_deserialize!{ - func: $name ( $( $arg: $ty ),* ); - } - )* - }; - - (func: deserialize_enum ( $( $arg:ident : $ty:ty ),* );) => { - fn deserialize_enum( - &mut self, - $(_: $ty,)* - _visitor: V, - ) -> ::std::result::Result - where V: ::serde::de::EnumVisitor - { - Err(::serde::de::Error::invalid_type(::serde::de::Type::Enum)) - } - }; - - (func: $name:ident ( $( $arg:ident : $ty:ty ),* );) => { - #[inline] - fn $name( - &mut self, - $(_: $ty,)* - visitor: V, - ) -> ::std::result::Result - where V: ::serde::de::Visitor - { - self.deserialize(visitor) - } - }; -} - -impl de::Deserializer for Decoder { - type Error = DecodeError; - - fn deserialize(&mut self, mut visitor: V) - -> Result - where V: de::Visitor - { - match self.toml.take() { - 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(); - visitor.visit_seq(SeqDeserializer::new(iter, len, &mut self.toml)) - } - Some(Value::Table(t)) => { - visitor.visit_map(MapVisitor { - iter: t.into_iter(), - de: self, - key: None, - value: None, - }) - } - None => Err(self.err(DecodeErrorKind::EndOfStream)), - } - } - - fn deserialize_bool(&mut self, mut visitor: V) - -> Result - where V: de::Visitor - { - match self.toml.take() { - Some(Value::Boolean(b)) => visitor.visit_bool(b), - ref found => Err(self.mismatch("bool", found)), - } - } - - fn deserialize_i8(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_i16(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_i32(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_i64(&mut self, mut visitor: V) - -> Result - where V: de::Visitor - { - match self.toml.take() { - Some(Value::Integer(f)) => visitor.visit_i64(f), - ref found => Err(self.mismatch("integer", found)), - } - } - - fn deserialize_isize(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_u8(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_u16(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_u32(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_u64(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_usize(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_i64(visitor) - } - - fn deserialize_f32(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_f64(visitor) - } - - fn deserialize_f64(&mut self, mut visitor: V) - -> Result - where V: de::Visitor - { - match self.toml.take() { - Some(Value::Float(f)) => visitor.visit_f64(f), - ref found => Err(self.mismatch("float", found)), - } - } - - fn deserialize_str(&mut self, mut visitor: V) - -> Result - 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_string(&mut self, visitor: V) - -> Result - where V: de::Visitor, - { - self.deserialize_str(visitor) - } - - fn deserialize_char(&mut self, mut visitor: V) - -> Result - 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(&mut self, mut visitor: V) - -> Result - where V: de::Visitor - { - if self.toml.is_none() { - visitor.visit_none() - } else { - visitor.visit_some(self) - } - } - - fn deserialize_seq(&mut self, mut visitor: V) - -> Result - where V: de::Visitor, - { - if self.toml.is_none() { - let iter = None::.into_iter(); - visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0)) - } else { - self.deserialize(visitor) - } - } - - fn deserialize_map(&mut self, mut visitor: V) - -> Result - 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(&mut self, - _enum: &str, - variants: &[&str], - mut visitor: V) -> Result - where V: de::EnumVisitor, - { - // When decoding enums, this crate takes the strategy of trying to - // decode the current TOML as all of the possible variants, returning - // success on the first one that succeeds. - // - // Note that fidelity of the errors returned here is a little nebulous, - // but we try to return the error that had the relevant field as the - // longest field. This way we hopefully match an error against what was - // most likely being written down without losing too much info. - let mut first_error = None::; - - for variant in 0..variants.len() { - let mut de = VariantVisitor { - de: self.sub_decoder(self.toml.clone(), ""), - variant: variant, - }; - - match visitor.visit(&mut de) { - Ok(value) => { - self.toml = de.de.toml; - return Ok(value); - } - Err(e) => { - if let Some(ref first) = first_error { - let my_len = e.field.as_ref().map(|s| s.len()); - let first_len = first.field.as_ref().map(|s| s.len()); - if my_len <= first_len { - continue - } - } - first_error = Some(e); - } - } - } - - Err(first_error.unwrap_or_else(|| self.err(DecodeErrorKind::NoEnumVariants))) - } - - // When #[derive(Deserialize)] encounters an unknown struct field it will - // call this method (somehow), and we want to preserve all unknown struct - // fields to return them upwards (to warn about unused keys), so we override - // that here to not tamper with our own internal state. - fn deserialize_ignored_any(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - use serde::de::value::ValueDeserializer; - let mut d = <() as ValueDeserializer>::into_deserializer(()); - d.deserialize(visitor) - } - - fn deserialize_bytes(&mut self, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_seq(visitor) - } - - fn deserialize_seq_fixed_size(&mut self, _len: usize, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_seq(visitor) - } - - fn deserialize_newtype_struct(&mut self, _name: &'static str, visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_seq(visitor) - } - - fn deserialize_tuple_struct(&mut self, - _name: &'static str, - _len: usize, - visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_seq(visitor) - } - - fn deserialize_struct(&mut self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_map(visitor) - } - - fn deserialize_tuple(&mut self, - _len: usize, - visitor: V) - -> Result - where V: de::Visitor - { - self.deserialize_seq(visitor) - } - - forward_to_deserialize!{ - deserialize_unit(); - deserialize_unit_struct(name: &'static str); - deserialize_struct_field(); - } -} - -struct VariantVisitor { - de: Decoder, - variant: usize, -} - -impl de::VariantVisitor for VariantVisitor { - type Error = DecodeError; - - fn visit_variant(&mut self) -> Result - where V: de::Deserialize - { - use serde::de::value::ValueDeserializer; - - let mut de = self.variant.into_deserializer(); - - de::Deserialize::deserialize(&mut de) - } - - fn visit_unit(&mut self) -> Result<(), DecodeError> { - de::Deserialize::deserialize(&mut self.de) - } - - fn visit_newtype(&mut self) -> Result - where T: de::Deserialize, - { - de::Deserialize::deserialize(&mut self.de) - } - - fn visit_tuple(&mut self, - _len: usize, - visitor: V) -> Result - where V: de::Visitor, - { - de::Deserializer::deserialize(&mut self.de, visitor) - } - - fn visit_struct(&mut self, - _fields: &'static [&'static str], - visitor: V) -> Result - where V: de::Visitor, - { - de::Deserializer::deserialize(&mut self.de, visitor) - } -} - -struct SeqDeserializer<'a, I> { - iter: I, - len: usize, - toml: &'a mut Option, -} - -impl<'a, I> SeqDeserializer<'a, I> where I: Iterator { - fn new(iter: I, len: usize, toml: &'a mut Option) -> Self { - SeqDeserializer { - iter: iter, - len: len, - toml: toml, - } - } - - fn put_value_back(&mut self, v: Value) { - *self.toml = self.toml.take().or(Some(Value::Array(Vec::new()))); - match self.toml.as_mut().unwrap() { - &mut Value::Array(ref mut a) => { - a.push(v); - }, - _ => unreachable!(), - } - } -} - -impl<'a, I> de::Deserializer for SeqDeserializer<'a, I> - where I: Iterator, -{ - type Error = DecodeError; - - fn deserialize(&mut self, mut visitor: V) - -> Result - where V: de::Visitor, - { - visitor.visit_seq(self) - } - - forward_to_deserialize!{ - deserialize_bool(); - deserialize_usize(); - deserialize_u8(); - deserialize_u16(); - deserialize_u32(); - deserialize_u64(); - deserialize_isize(); - deserialize_i8(); - deserialize_i16(); - deserialize_i32(); - deserialize_i64(); - deserialize_f32(); - deserialize_f64(); - deserialize_char(); - deserialize_str(); - deserialize_string(); - deserialize_unit(); - deserialize_option(); - deserialize_seq(); - deserialize_seq_fixed_size(len: usize); - deserialize_bytes(); - deserialize_map(); - deserialize_unit_struct(name: &'static str); - deserialize_newtype_struct(name: &'static str); - deserialize_tuple_struct(name: &'static str, len: usize); - deserialize_struct(name: &'static str, fields: &'static [&'static str]); - deserialize_struct_field(); - deserialize_tuple(len: usize); - deserialize_enum(name: &'static str, variants: &'static [&'static str]); - deserialize_ignored_any(); - } -} - -impl<'a, I> de::SeqVisitor for SeqDeserializer<'a, I> - where I: Iterator -{ - type Error = DecodeError; - - fn visit(&mut self) -> Result, DecodeError> - where V: de::Deserialize - { - match self.iter.next() { - Some(value) => { - self.len -= 1; - let mut de = Decoder::new(value); - let v = try!(de::Deserialize::deserialize(&mut de)); - if let Some(t) = de.toml { - self.put_value_back(t); - } - Ok(Some(v)) - } - None => Ok(None), - } - } - - fn end(&mut self) -> Result<(), DecodeError> { - if self.len == 0 { - Ok(()) - } else { - Err(de::Error::end_of_stream()) - } - } - - fn size_hint(&self) -> (usize, Option) { - (self.len, Some(self.len)) - } -} - -impl de::Error for DecodeError { - fn custom>(msg: T) -> DecodeError { - DecodeError { - field: None, - kind: DecodeErrorKind::CustomError(msg.into()), - } - } - fn end_of_stream() -> DecodeError { - DecodeError { field: None, kind: DecodeErrorKind::EndOfStream } - } - fn missing_field(name: &'static str) -> DecodeError { - DecodeError { - field: Some(name.to_string()), - kind: DecodeErrorKind::ExpectedField(None), - } - } - fn unknown_field(name: &str) -> DecodeError { - DecodeError { - field: Some(name.to_string()), - 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> { - iter: I, - de: &'a mut Decoder, - key: Option, - value: Option, -} - -impl<'a, I> MapVisitor<'a, I> { - fn put_value_back(&mut self, v: Value) { - self.de.toml = self.de.toml.take().or_else(|| { - Some(Value::Table(BTreeMap::new())) - }); - - match self.de.toml.as_mut().unwrap() { - &mut Value::Table(ref mut t) => { - t.insert(self.key.take().unwrap(), v); - }, - _ => unreachable!(), - } - } -} - -impl<'a, I> de::MapVisitor for MapVisitor<'a, I> - where I: Iterator -{ - type Error = DecodeError; - - fn visit_key(&mut self) -> Result, DecodeError> - where K: de::Deserialize - { - while let Some((k, v)) = self.iter.next() { - let mut dec = self.de.sub_decoder(Some(Value::String(k.clone())), &k); - self.key = Some(k); - - match de::Deserialize::deserialize(&mut dec) { - Ok(val) => { - self.value = Some(v); - return Ok(Some(val)) - } - - // If this was an unknown field, then we put the toml value - // back into the map and keep going. - Err(DecodeError {kind: DecodeErrorKind::UnknownField, ..}) => { - self.put_value_back(v); - } - - Err(e) => return Err(e), - } - } - Ok(None) - } - - fn visit_value(&mut self) -> Result - where V: de::Deserialize - { - match self.value.take() { - Some(t) => { - let mut dec = { - // Borrowing the key here because Rust doesn't have - // non-lexical borrows yet. - let key = match self.key { - Some(ref key) => &**key, - None => "" - }; - - self.de.sub_decoder(Some(t), key) - }; - let v = try!(de::Deserialize::deserialize(&mut dec)); - if let Some(t) = dec.toml { - self.put_value_back(t); - } - Ok(v) - }, - None => Err(de::Error::end_of_stream()) - } - } - - 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(()) - } - - fn missing_field(&mut self, field_name: &'static str) - -> Result where V: de::Deserialize { - // See if the type can deserialize from a unit. - match de::Deserialize::deserialize(&mut UnitDeserializer) { - Err(DecodeError { - kind: DecodeErrorKind::InvalidType(..), - field, - }) => Err(DecodeError { - field: field.or(Some(field_name.to_string())), - kind: DecodeErrorKind::ExpectedField(None), - }), - v => v, - } - } -} - -struct UnitDeserializer; - -impl de::Deserializer for UnitDeserializer { - type Error = DecodeError; - - fn deserialize(&mut self, mut visitor: V) - -> Result - where V: de::Visitor, - { - visitor.visit_unit() - } - - fn deserialize_option(&mut self, mut visitor: V) - -> Result - where V: de::Visitor, - { - visitor.visit_none() - } - - forward_to_deserialize!{ - deserialize_bool(); - deserialize_usize(); - deserialize_u8(); - deserialize_u16(); - deserialize_u32(); - deserialize_u64(); - deserialize_isize(); - deserialize_i8(); - deserialize_i16(); - deserialize_i32(); - deserialize_i64(); - deserialize_f32(); - deserialize_f64(); - deserialize_char(); - deserialize_str(); - deserialize_string(); - deserialize_unit(); - deserialize_seq(); - deserialize_seq_fixed_size(len: usize); - deserialize_bytes(); - deserialize_map(); - deserialize_unit_struct(name: &'static str); - deserialize_newtype_struct(name: &'static str); - deserialize_tuple_struct(name: &'static str, len: usize); - deserialize_struct(name: &'static str, fields: &'static [&'static str]); - deserialize_struct_field(); - deserialize_tuple(len: usize); - deserialize_enum(name: &'static str, variants: &'static [&'static str]); - deserialize_ignored_any(); - } -} - -impl de::Deserialize for Value { - fn deserialize(deserializer: &mut D) -> Result - where D: de::Deserializer - { - struct ValueVisitor; - - impl de::Visitor for ValueVisitor { - type Value = Value; - - fn visit_bool(&mut self, value: bool) -> Result { - Ok(Value::Boolean(value)) - } - - fn visit_i64(&mut self, value: i64) -> Result { - Ok(Value::Integer(value)) - } - - fn visit_f64(&mut self, value: f64) -> Result { - Ok(Value::Float(value)) - } - - fn visit_str(&mut self, value: &str) -> Result { - Ok(Value::String(value.into())) - } - - fn visit_string(&mut self, value: String) -> Result { - Ok(Value::String(value)) - } - - fn visit_seq(&mut self, visitor: V) -> Result - where V: de::SeqVisitor - { - let values = try!(de::impls::VecVisitor::new().visit_seq(visitor)); - Ok(Value::Array(values)) - } - - fn visit_map(&mut self, visitor: V) -> Result - where V: de::MapVisitor - { - let mut v = de::impls::BTreeMapVisitor::new(); - let values = try!(v.visit_map(visitor)); - Ok(Value::Table(values)) - } - } - - deserializer.deserialize(ValueVisitor) - } -} -- cgit v1.2.3