From 61fa3206a5b78e11ba9684ae0667226273d2edc9 Mon Sep 17 00:00:00 2001 From: Artem Biryukov Date: Fri, 10 Mar 2017 13:24:42 +0500 Subject: Add Value::into_str and Value::into_array Other changes inside of Deserializer --- lib/src/de.rs | 168 ++++--------------------------------------------------- lib/src/value.rs | 32 +++++++++++ 2 files changed, 42 insertions(+), 158 deletions(-) diff --git a/lib/src/de.rs b/lib/src/de.rs index a59d950..d1673d5 100644 --- a/lib/src/de.rs +++ b/lib/src/de.rs @@ -1,6 +1,7 @@ use serde::de; use value::{Value, ValueKind}; use error::*; +use std::borrow::Cow; use std::iter::Peekable; use std::collections::HashMap; use std::collections::hash_map::Drain; @@ -12,169 +13,20 @@ impl de::Deserializer for Value { fn deserialize(self, visitor: V) -> Result { // Deserialize based on the underlying type match self.kind { - ValueKind::Boolean(value) => { - visitor.visit_bool(value) - } - - ValueKind::Table(map) => { - visitor.visit_map(MapVisitor::new(map)) - } - + ValueKind::Integer(i) => visitor.visit_i64(i), + ValueKind::Boolean(b) => visitor.visit_bool(b), + ValueKind::Float(f) => visitor.visit_f64(f), + // ValueKind::String(Cow::Borrowed(s)) => visitor.visit_str(s), + // ValueKind::String(Cow::Owned(s)) => visitor.visit_string(s), + ValueKind::Table(map) => visitor.visit_map(MapVisitor::new(map)), _ => { unimplemented!(); } } } - #[inline] - fn deserialize_bool(self, visitor: V) -> Result { - visitor.visit_bool(self.into_bool()?) - } - - #[inline] - fn deserialize_u8(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_u16(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_u32(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_u64(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_i8(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_i16(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_i32(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_i64(self, visitor: V) -> Result { - visitor.visit_i64(self.into_int()?) - } - - #[inline] - fn deserialize_f32(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_f64(self, visitor: V) -> Result { - visitor.visit_f64(self.into_float()?) - } - - #[inline] - fn deserialize_char(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_str(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_string(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_bytes(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_byte_buf(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_option(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_unit(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_unit_struct(self, - name: &'static str, - visitor: V) - -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_newtype_struct(self, - name: &'static str, - visitor: V) - -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_seq(self, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_seq_fixed_size(self, - len: usize, - visitor: V) - -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_tuple(self, len: usize, visitor: V) -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_tuple_struct(self, - name: &'static str, - len: usize, - visitor: V) - -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_enum(self, - name: &'static str, - variants: &'static [&'static str], - visitor: V) - -> Result { - unimplemented!(); - } - - #[inline] - fn deserialize_ignored_any(self, visitor: V) -> Result { - unimplemented!(); - } - forward_to_deserialize! { - map - struct - struct_field + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq + seq_fixed_size bytes byte_buf map struct unit enum newtype_struct + struct_field ignored_any unit_struct tuple_struct tuple option } } diff --git a/lib/src/value.rs b/lib/src/value.rs index 87e45bc..455e951 100644 --- a/lib/src/value.rs +++ b/lib/src/value.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::HashMap; use std::fmt::Display; use error::*; @@ -187,6 +188,37 @@ impl Value { ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Seq, &"a floating point")), } } + + /// Returns `self` into a str, if possible. + pub fn into_str(self) -> Result { + match self.kind { + ValueKind::String(value) => Ok(value), + + // Cannot convert + ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), &"a string")), + ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), &"a string")), + ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), &"a string")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, &"a string")), + ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Map, &"a string")), + ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, &"a string")), + } + } + + /// Returns `self` into an array, if possible + pub fn into_array(self) -> Result> { + match self.kind { + ValueKind::Array(value) => Ok(value), + + // Cannot convert + ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), &"an array")), + ValueKind::String(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Str(value), &"an array")), + ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), &"an array")), + ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), &"an array")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, &"an array")), + ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Map, &"an array")), + } + } + /// If the `Value` is a Table, returns the associated Map. pub fn into_table(self) -> Result> { match self.kind { -- cgit v1.2.3 From fbcc7238e100e07d279e100a36a2eb76f53e7006 Mon Sep 17 00:00:00 2001 From: Artem Biryukov Date: Fri, 10 Mar 2017 18:01:54 +0500 Subject: Started refactoring on Value and Deserialization --- lib/src/de.rs | 52 +++++++++++--------------------- lib/src/error.rs | 5 +-- lib/src/value.rs | 92 +++++++++++++++++++++++++++++--------------------------- 3 files changed, 67 insertions(+), 82 deletions(-) diff --git a/lib/src/de.rs b/lib/src/de.rs index d1673d5..369d6de 100644 --- a/lib/src/de.rs +++ b/lib/src/de.rs @@ -10,14 +10,16 @@ impl de::Deserializer for Value { type Error = ConfigError; #[inline] - fn deserialize(self, visitor: V) -> Result { + fn deserialize(self, visitor: V) -> Result + where V: de::Visitor, + { // Deserialize based on the underlying type match self.kind { ValueKind::Integer(i) => visitor.visit_i64(i), ValueKind::Boolean(b) => visitor.visit_bool(b), ValueKind::Float(f) => visitor.visit_f64(f), - // ValueKind::String(Cow::Borrowed(s)) => visitor.visit_str(s), - // ValueKind::String(Cow::Owned(s)) => visitor.visit_string(s), + ValueKind::String(s) => visitor.visit_string(s), + ValueKind::Array(values) => unimplemented!(), ValueKind::Table(map) => visitor.visit_map(MapVisitor::new(map)), _ => { unimplemented!(); } } @@ -32,6 +34,12 @@ impl de::Deserializer for Value { struct StrDeserializer<'a>(&'a str); +impl<'a> StrDeserializer<'a> { + fn new(key: &'a str) -> Self { + StrDeserializer(key) + } +} + impl<'a> de::Deserializer for StrDeserializer<'a> { type Error = ConfigError; @@ -41,35 +49,9 @@ impl<'a> de::Deserializer for StrDeserializer<'a> { } forward_to_deserialize! { - bool - u8 - u16 - u32 - u64 - i8 - i16 - i32 - i64 - f32 - f64 - char - str - string - bytes - byte_buf - option - unit - unit_struct - newtype_struct - seq - seq_fixed_size - tuple - tuple_struct - map - struct - struct_field - enum - ignored_any + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq + seq_fixed_size bytes byte_buf map struct unit enum newtype_struct + struct_field ignored_any unit_struct tuple_struct tuple option } } @@ -79,7 +61,7 @@ struct MapVisitor { } impl MapVisitor { - fn new(mut table: HashMap) -> MapVisitor { + fn new(mut table: HashMap) -> Self { MapVisitor { elements: table.drain().collect(), index: 0 } } } @@ -94,8 +76,8 @@ impl de::MapVisitor for MapVisitor { return Ok(None); } - let ref key_s = self.elements[0].0; - let key_de = StrDeserializer(&key_s); + let key_s = &self.elements[0].0; + let key_de = StrDeserializer(key_s); let key = de::DeserializeSeed::deserialize(seed, key_de)?; Ok(Some(key)) diff --git a/lib/src/error.rs b/lib/src/error.rs index 390057f..b97ebac 100644 --- a/lib/src/error.rs +++ b/lib/src/error.rs @@ -1,4 +1,5 @@ use std::error::Error; +use std::borrow::Cow; use std::result; use std::fmt; use serde::de; @@ -61,7 +62,7 @@ pub enum ConfigError { impl ConfigError { // FIXME: pub(crate) #[doc(hidden)] - pub fn invalid_type(origin: Option, unexpected: Unexpected, expected: &'static str) -> ConfigError { + pub fn invalid_type(origin: Option, unexpected: Unexpected, expected: &'static str) -> Self { ConfigError::Type { origin: origin, unexpected: unexpected, @@ -148,7 +149,7 @@ impl Error for ConfigError { } impl de::Error for ConfigError { - fn custom(msg: T) -> ConfigError { + fn custom(msg: T) -> Self { ConfigError::Message(msg.to_string()) } } diff --git a/lib/src/value.rs b/lib/src/value.rs index 455e951..5b0014a 100644 --- a/lib/src/value.rs +++ b/lib/src/value.rs @@ -1,4 +1,3 @@ -use std::borrow::Cow; use std::collections::HashMap; use std::fmt::Display; use error::*; @@ -7,14 +6,17 @@ use error::*; #[derive(Debug, Clone)] pub enum ValueKind { Nil, - String(String), + Boolean(bool), Integer(i64), Float(f64), - Boolean(bool), - Table(HashMap), - Array(Vec), + String(String), + Table(Table), + Array(Array), } +pub type Array = Vec; +pub type Table = HashMap; + impl Default for ValueKind { fn default() -> Self { ValueKind::Nil @@ -24,7 +26,7 @@ impl Default for ValueKind { impl From> for ValueKind where T: Into { - fn from(value: Option) -> ValueKind { + fn from(value: Option) -> Self { match value { Some(value) => value.into(), None => ValueKind::Nil, @@ -33,31 +35,31 @@ impl From> for ValueKind } impl From for ValueKind { - fn from(value: String) -> ValueKind { + fn from(value: String) -> Self { ValueKind::String(value.into()) } } impl<'a> From<&'a str> for ValueKind { - fn from(value: &'a str) -> ValueKind { + fn from(value: &'a str) -> Self { ValueKind::String(value.into()) } } impl From for ValueKind { - fn from(value: i64) -> ValueKind { + fn from(value: i64) -> Self { ValueKind::Integer(value) } } impl From for ValueKind { - fn from(value: f64) -> ValueKind { + fn from(value: f64) -> Self { ValueKind::Float(value) } } impl From for ValueKind { - fn from(value: bool) -> ValueKind { + fn from(value: bool) -> Self { ValueKind::Boolean(value) } } @@ -65,7 +67,7 @@ impl From for ValueKind { impl From> for ValueKind where T: Into { - fn from(values: HashMap) -> ValueKind { + fn from(values: HashMap) -> Self { let mut r = HashMap::new(); for (k, v) in values { @@ -79,7 +81,7 @@ impl From> for ValueKind impl From> for ValueKind where T: Into { - fn from(values: Vec) -> ValueKind { + fn from(values: Vec) -> Self { let mut l = Vec::new(); for v in values { @@ -116,7 +118,7 @@ pub struct Value { } impl Value { - pub fn new(origin: Option<&String>, kind: V) -> Value + pub fn new(origin: Option<&String>, kind: V) -> Self where V: Into { Value { @@ -138,14 +140,14 @@ impl Value { "0" | "false" | "off" | "no" => Ok(false), // Unexpected string value - s @ _ => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Str(s.into()), &"a boolean")), + s @ _ => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Str(s.into()), "a boolean")), } } // Unexpected type - ValueKind::Nil => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Unit, &"a boolean")), - ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Map, &"a boolean")), - ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Seq, &"a boolean")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Unit, "a boolean")), + ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Map, "a boolean")), + ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Seq, "a boolean")), } } @@ -156,16 +158,16 @@ impl Value { ValueKind::String(ref s) => s.parse().map_err(|_| { // Unexpected string - ConfigError::invalid_type(self.origin.clone(), Unexpected::Str(s.clone()), &"an integer") + ConfigError::invalid_type(self.origin.clone(), Unexpected::Str(s.clone()), "an integer") }), ValueKind::Boolean(value) => Ok(if value { 1 } else { 0 }), ValueKind::Float(value) => Ok(value.round() as i64), // Unexpected type - ValueKind::Nil => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Unit, &"an integer")), - ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Map, &"an integer")), - ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Seq, &"an integer")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Unit, "an integer")), + ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Map, "an integer")), + ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Seq, "an integer")), } } @@ -176,16 +178,16 @@ impl Value { ValueKind::String(ref s) => s.parse().map_err(|_| { // Unexpected string - ConfigError::invalid_type(self.origin.clone(), Unexpected::Str(s.clone()), &"a floating point") + ConfigError::invalid_type(self.origin.clone(), Unexpected::Str(s.clone()), "a floating point") }), ValueKind::Integer(value) => Ok(value as f64), ValueKind::Boolean(value) => Ok(if value { 1.0 } else { 0.0 }), // Unexpected type - ValueKind::Nil => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Unit, &"a floating point")), - ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Map, &"a floating point")), - ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Seq, &"a floating point")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Unit, "a floating point")), + ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Map, "a floating point")), + ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin.clone(), Unexpected::Seq, "a floating point")), } } @@ -195,12 +197,12 @@ impl Value { ValueKind::String(value) => Ok(value), // Cannot convert - ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), &"a string")), - ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), &"a string")), - ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), &"a string")), - ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, &"a string")), - ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Map, &"a string")), - ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, &"a string")), + ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), "a string")), + ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), "a string")), + ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), "a string")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "a string")), + ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "a string")), + ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "a string")), } } @@ -210,12 +212,12 @@ impl Value { ValueKind::Array(value) => Ok(value), // Cannot convert - ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), &"an array")), - ValueKind::String(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Str(value), &"an array")), - ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), &"an array")), - ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), &"an array")), - ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, &"an array")), - ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Map, &"an array")), + ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), "an array")), + ValueKind::String(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Str(value), "an array")), + ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), "an array")), + ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), "an array")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "an array")), + ValueKind::Table(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "an array")), } } @@ -225,12 +227,12 @@ impl Value { ValueKind::Table(value) => Ok(value), // Cannot convert - ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), &"a map")), - ValueKind::String(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Str(value), &"a map")), - ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), &"a map")), - ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), &"a map")), - ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, &"a map")), - ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, &"a map")), + ValueKind::Float(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), "a map")), + ValueKind::String(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Str(value), "a map")), + ValueKind::Integer(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Integer(value), "a map")), + ValueKind::Boolean(value) => Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), "a map")), + ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "a map")), + ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "a map")), } } } @@ -238,7 +240,7 @@ impl Value { impl From for Value where T: Into { - fn from(value: T) -> Value { + fn from(value: T) -> Self { Value { origin: None, kind: value.into(), -- cgit v1.2.3