diff options
author | Ryan Leckey <leckey.ryan@gmail.com> | 2017-07-30 14:22:50 -0700 |
---|---|---|
committer | Ryan Leckey <leckey.ryan@gmail.com> | 2017-07-30 14:22:50 -0700 |
commit | cb4888dbbd3f2ebd1bd4e35fb07fb2fe0facafe8 (patch) | |
tree | 6eb95488f03b6821842b1acdeb92eb3ed01184ec /src | |
parent | a0fc361a4b3413ea99631786b4b256bb377788d5 (diff) |
Impl Deserializer for Config (to forward Value)
Diffstat (limited to 'src')
-rw-r--r-- | src/config.rs | 12 | ||||
-rw-r--r-- | src/de.rs | 112 |
2 files changed, 118 insertions, 6 deletions
diff --git a/src/config.rs b/src/config.rs index f890461..fac76a5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::ops::Deref; use std::str::FromStr; use std::fmt::Debug; -use serde::de::Deserialize; +use serde::de::{Deserialize, Deserializer}; use error::*; use source::Source; @@ -110,11 +110,6 @@ impl Config { Ok(self) } - /// Deserialize the entire configuration. - pub fn deserialize<'de, T: Deserialize<'de>>(&self) -> Result<T> { - T::deserialize(self.cache.clone()) - } - pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config> where T: Into<Value>, @@ -189,6 +184,11 @@ impl Config { pub fn get_array(&self, key: &str) -> Result<Vec<Value>> { self.get(key).and_then(Value::into_array) } + + /// Attempt to deserialize the entire configuration into the requested type. + pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> { + T::deserialize(self) + } } impl Source for Config { @@ -1,6 +1,7 @@ use serde::de; use value::{Value, ValueKind, ValueWithKey}; use error::*; +use config::Config; use std::borrow::Cow; use std::iter::Peekable; use std::collections::HashMap; @@ -325,3 +326,114 @@ impl<'de> de::MapAccess<'de> for MapAccess { de::DeserializeSeed::deserialize(seed, self.elements.remove(0).1) } } + +impl<'de> de::Deserializer<'de> for Config { + type Error = ConfigError; + + #[inline] + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value> + where + V: de::Visitor<'de>, + { + // Deserialize based on the underlying type + match self.cache.kind { + ValueKind::Nil => visitor.visit_unit(), + ValueKind::Integer(i) => visitor.visit_i64(i), + ValueKind::Boolean(b) => visitor.visit_bool(b), + ValueKind::Float(f) => visitor.visit_f64(f), + ValueKind::String(s) => visitor.visit_string(s), + ValueKind::Array(values) => visitor.visit_seq(SeqAccess::new(values)), + ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map)), + } + } + + #[inline] + fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + visitor.visit_bool(self.cache.into_bool()?) + } + + #[inline] + fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + // FIXME: This should *fail* if the value does not fit in the requets integer type + visitor.visit_i8(self.cache.into_int()? as i8) + } + + #[inline] + fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + // FIXME: This should *fail* if the value does not fit in the requets integer type + visitor.visit_i16(self.cache.into_int()? as i16) + } + + #[inline] + fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + // FIXME: This should *fail* if the value does not fit in the requets integer type + visitor.visit_i32(self.cache.into_int()? as i32) + } + + #[inline] + fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + visitor.visit_i64(self.cache.into_int()?) + } + + #[inline] + fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + // FIXME: This should *fail* if the value does not fit in the requets integer type + visitor.visit_u8(self.cache.into_int()? as u8) + } + + #[inline] + fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + // FIXME: This should *fail* if the value does not fit in the requets integer type + visitor.visit_u16(self.cache.into_int()? as u16) + } + + #[inline] + fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + // FIXME: This should *fail* if the value does not fit in the requets integer type + visitor.visit_u32(self.cache.into_int()? as u32) + } + + #[inline] + fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + // FIXME: This should *fail* if the value does not fit in the requets integer type + visitor.visit_u64(self.cache.into_int()? as u64) + } + + #[inline] + fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + visitor.visit_f32(self.cache.into_float()? as f32) + } + + #[inline] + fn deserialize_f64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + visitor.visit_f64(self.cache.into_float()?) + } + + #[inline] + fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + visitor.visit_string(self.cache.into_str()?) + } + + #[inline] + fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> { + visitor.visit_string(self.cache.into_str()?) + } + + #[inline] + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> + where + V: de::Visitor<'de>, + { + // Match an explicit nil as None and everything else as Some + match self.cache.kind { + ValueKind::Nil => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + forward_to_deserialize_any! { + char seq + bytes byte_buf map struct unit enum newtype_struct + identifier ignored_any unit_struct tuple_struct tuple + } +} |