From 86771ac343c8c95df61c48895c9d679391f1aff9 Mon Sep 17 00:00:00 2001 From: XX Date: Fri, 6 Apr 2018 15:53:03 +0300 Subject: Add config serialize ability --- src/config.rs | 11 +- src/error.rs | 7 + src/lib.rs | 1 + src/ser.rs | 611 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 src/ser.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 33d17bc..60f8551 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,11 +3,13 @@ use std::ops::Deref; use std::str::FromStr; use std::fmt::Debug; use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer}; use error::*; use source::Source; +use ser::ConfigSerializer; -use value::{Value, ValueWithKey}; +use value::{Value, ValueKind, ValueWithKey}; use path; #[derive(Clone, Debug)] @@ -190,6 +192,13 @@ impl Config { T::deserialize(self) } + /// Attempt to deserialize the entire configuration into the requested type. + pub fn try_from(from: &T) -> Result { + let mut serializer = ConfigSerializer::default(); + from.serialize(&mut serializer)?; + Ok(serializer.output) + } + #[deprecated(since="0.7.0", note="please use 'try_into' instead")] pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result { self.try_into() diff --git a/src/error.rs b/src/error.rs index eff3c7c..56c827a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use std::result; use std::fmt; use serde::de; +use serde::ser; use nom; #[derive(Debug)] @@ -201,3 +202,9 @@ impl de::Error for ConfigError { ConfigError::Message(msg.to_string()) } } + +impl ser::Error for ConfigError { + fn custom(msg: T) -> Self { + ConfigError::Message(msg.to_string()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 6178375..187e2ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,7 @@ extern crate serde_hjson; mod error; mod value; mod de; +mod ser; mod path; mod source; mod config; diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..7ea1a43 --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,611 @@ +use std::mem; +use std::fmt::Display; +use serde::ser; + +use Config; +use value::{Value, ValueKind, ValueWithKey}; +use error::*; + +#[derive(Default, Debug)] +pub struct ConfigSerializer { + keys: Vec<(String, Option)>, + pub output: Config, +} + +impl ConfigSerializer { + fn serialize_primitive(&mut self, value: T) -> Result<()> + where T: Into + Display + { + let key = match self.last_key_index_pair() { + Some((key, Some(index))) => format!("{}[{}]", key, index), + Some((key, None)) => key.to_string(), + None => return Err(ConfigError::Message(format!("key is not found for value {}", value))) + }; + self.output.set(&key, value.into())?; + Ok(()) + } + + fn last_key_index_pair(&self) -> Option<(&str, Option)> { + let len = self.keys.len(); + if len > 0 { + self.keys.get(len - 1) + .map(|&(ref key, opt)| (key.as_str(), opt)) + } else { + None + } + } + + fn inc_last_key_index(&mut self) -> Result<()> { + let len = self.keys.len(); + if len > 0 { + self.keys.get_mut(len - 1) + .map(|pair| { + pair.1 = pair.1.map(|i| i + 1).or(Some(0)) + }) + .ok_or(ConfigError::Message( + format!("last key is not found in {} keys", len) + )) + } else { + Err(ConfigError::Message("keys is empty".to_string())) + } + } + + fn make_full_key(&self, key: &str) -> String { + let len = self.keys.len(); + if len > 0 { + if let Some(&(ref prev_key, index)) = self.keys.get(len - 1) { + return if let Some(index) = index { + format!("{}[{}].{}", prev_key, index, key) + } else { + format!("{}.{}", prev_key, key) + } + } + } + key.to_string() + } + + fn push_key(&mut self, key: &str) { + let full_key = self.make_full_key(key); + self.keys.push((full_key, None)); + } + + fn pop_key(&mut self) -> Option<(String, Option)> { + self.keys.pop() + } +} + +impl<'a> ser::Serializer for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + type SerializeSeq = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + fn serialize_bool(self, v: bool) -> Result { + self.serialize_primitive(v) + } + + fn serialize_i8(self, v: i8) -> Result { + self.serialize_i64(v as i64) + } + + fn serialize_i16(self, v: i16) -> Result { + self.serialize_i64(v as i64) + } + + fn serialize_i32(self, v: i32) -> Result { + self.serialize_i64(v as i64) + } + + fn serialize_i64(self, v: i64) -> Result { + self.serialize_primitive(v) + } + + fn serialize_u8(self, v: u8) -> Result { + self.serialize_u64(v as u64) + } + + fn serialize_u16(self, v: u16) -> Result { + self.serialize_u64(v as u64) + } + + fn serialize_u32(self, v: u32) -> Result { + self.serialize_u64(v as u64) + } + + fn serialize_u64(self, v: u64) -> Result { + if v > (i64::max_value() as u64) { + Err(ConfigError::Message( + format!("value {} is greater than the max {}", v, i64::max_value()) + )) + } else { + self.serialize_i64(v as i64) + } + } + + fn serialize_f32(self, v: f32) -> Result { + self.serialize_f64(v as f64) + } + + fn serialize_f64(self, v: f64) -> Result { + self.serialize_primitive(v) + } + + fn serialize_char(self, v: char) -> Result { + self.serialize_primitive(v.to_string()) + } + + fn serialize_str(self, v: &str) -> Result { + self.serialize_primitive(v.to_string()) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + use serde::ser::SerializeSeq; + let mut seq = self.serialize_seq(Some(v.len()))?; + for byte in v { + seq.serialize_element(byte)?; + } + seq.end() + } + + fn serialize_none(self) -> Result { + self.serialize_unit() + } + + fn serialize_some(self, value: &T) -> Result + where T: ?Sized + ser::Serialize + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + self.serialize_primitive(Value::from(ValueKind::Nil)) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + fn serialize_unit_variant(self, _name: &'static str, _variant_index: u32, variant: &'static str) + -> Result + { + self.serialize_str(&variant.to_lowercase()) + } + + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result + where T: ?Sized + ser::Serialize + { + value.serialize(self) + } + + fn serialize_newtype_variant(self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T) + -> Result + where T: ?Sized + ser::Serialize + { + self.push_key(&variant.to_lowercase()); + value.serialize(&mut *self)?; + self.pop_key(); + Ok(()) + } + + fn serialize_seq(self, _len: Option) -> Result { + Ok(self) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct(self, _name: &'static str, len: usize) + -> Result + { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant(self, name: &'static str, _variant_index: u32, variant: &'static str, _len: usize) + -> Result + { + self.push_key(&variant.to_lowercase()); + Ok(self) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(self) + } + + fn serialize_struct(self, _name: &'static str, len: usize) -> Result { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant(self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize) + -> Result + { + self.push_key(&variant.to_lowercase()); + Ok(self) + } +} + +impl<'a> ser::SerializeSeq for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + self.inc_last_key_index()?; + value.serialize(&mut **self)?; + Ok(()) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a> ser::SerializeTuple for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + self.inc_last_key_index()?; + value.serialize(&mut **self)?; + Ok(()) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a> ser::SerializeTupleStruct for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + self.inc_last_key_index()?; + value.serialize(&mut **self)?; + Ok(()) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a> ser::SerializeTupleVariant for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + self.inc_last_key_index()?; + value.serialize(&mut **self)?; + Ok(()) + } + + fn end(self) -> Result { + self.pop_key(); + Ok(()) + } +} + +impl<'a> ser::SerializeMap for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + + fn serialize_key(&mut self, key: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + let key_serializer = StringKeySerializer; + let key = key.serialize(key_serializer)?; + self.push_key(&key); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + value.serialize(&mut **self)?; + self.pop_key(); + Ok(()) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a> ser::SerializeStruct for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + self.push_key(key); + value.serialize(&mut **self)?; + self.pop_key(); + Ok(()) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a> ser::SerializeStructVariant for &'a mut ConfigSerializer { + type Ok = (); + type Error = ConfigError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + self.push_key(key); + value.serialize(&mut **self)?; + self.pop_key(); + Ok(()) + } + + fn end(self) -> Result { + self.pop_key(); + Ok(()) + } +} + +pub struct StringKeySerializer; + +impl ser::Serializer for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + type SerializeSeq = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + fn serialize_bool(self, v: bool) -> Result { + Ok(v.to_string()) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(v.to_string()) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(v.to_string()) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(v.to_string()) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(v.to_string()) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(v.to_string()) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(v.to_string()) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(v.to_string()) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(v.to_string()) + } + + fn serialize_f32(self, v: f32) -> Result { + Ok(v.to_string()) + } + + fn serialize_f64(self, v: f64) -> Result { + Ok(v.to_string()) + } + + fn serialize_char(self, v: char) -> Result { + Ok(v.to_string()) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(v.to_string()) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + Ok(String::from_utf8_lossy(v).to_string()) + } + + fn serialize_none(self) -> Result { + self.serialize_unit() + } + + fn serialize_some(self, value: &T) -> Result + where T: ?Sized + ser::Serialize + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + Ok(String::new()) + } + + fn serialize_unit_struct(self, _name: &str) -> Result { + self.serialize_unit() + } + + fn serialize_unit_variant(self, _name: &str, _variant_index: u32, variant: &str) -> Result { + Ok(variant.to_lowercase()) + } + + fn serialize_newtype_struct(self, _name: &str, value: &T) -> Result + where T: ?Sized + ser::Serialize + { + value.serialize(self) + } + + fn serialize_newtype_variant(self, _name: &str, _variant_index: u32, _variant: &str, value: &T) + -> Result + where T: ?Sized + ser::Serialize + { + value.serialize(self) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(ConfigError::Message("seq can't serialize to string key".to_string())) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(ConfigError::Message("tuple can't serialize to string key".to_string())) + } + + fn serialize_tuple_struct(self, name: &str, _len: usize) -> Result { + Err(ConfigError::Message(format!("tuple struct {} can't serialize to string key", name))) + } + + fn serialize_tuple_variant(self, name: &str, _variant_index: u32, variant: &str, _len: usize) + -> Result + { + Err(ConfigError::Message(format!("tuple variant {}::{} can't serialize to string key", name, variant))) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(ConfigError::Message("map can't serialize to string key".to_string())) + } + + fn serialize_struct(self, name: &str, _len: usize) -> Result { + Err(ConfigError::Message(format!("struct {} can't serialize to string key", name))) + } + + fn serialize_struct_variant(self, name: &str, _variant_index: u32, variant: &str, _len: usize) + -> Result + { + Err(ConfigError::Message(format!("struct variant {}::{} can't serialize to string key", name, variant))) + } +} + + +impl ser::SerializeSeq for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn end(self) -> Result { + unreachable!() + } +} + +impl ser::SerializeTuple for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn end(self) -> Result { + unreachable!() + } +} + +impl ser::SerializeTupleStruct for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn end(self) -> Result { + unreachable!() + } +} + +impl ser::SerializeTupleVariant for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn end(self) -> Result { + unreachable!() + } +} + +impl ser::SerializeMap for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + + fn serialize_key(&mut self, key: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn end(self) -> Result { + unreachable!() + } +} + +impl ser::SerializeStruct for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn end(self) -> Result { + unreachable!() + } +} + +impl ser::SerializeStructVariant for StringKeySerializer { + type Ok = String; + type Error = ConfigError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where T: ?Sized + ser::Serialize + { + unreachable!() + } + + fn end(self) -> Result { + unreachable!() + } +} -- cgit v1.2.3 From 52975a263612cea41fb3047a5e8f2bac9e1819b4 Mon Sep 17 00:00:00 2001 From: XX Date: Sun, 8 Apr 2018 16:25:56 +0300 Subject: Fix initialy set arr path --- src/path/mod.rs | 171 +++++++++++++++++++++++++++++++++++------------------ src/path/parser.rs | 9 +++ 2 files changed, 124 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/path/mod.rs b/src/path/mod.rs index 258c4c4..f042992 100644 --- a/src/path/mod.rs +++ b/src/path/mod.rs @@ -58,77 +58,138 @@ impl Expression { } } - Expression::Subscript(expr, index) => match expr.get(root) { - Some(value) => match value.kind { - ValueKind::Array(ref array) => { - let index = sindex_to_uindex(index, array.len()); - - if index >= array.len() { - None - } else { - Some(&array[index]) + Expression::Subscript(expr, index) => { + match expr.get(root) { + Some(value) => match value.kind { + ValueKind::Array(ref array) => { + let index = sindex_to_uindex(index, array.len()); + + if index >= array.len() { + None + } else { + Some(&array[index]) + } } - } - _ => None, - }, + _ => None, + }, - _ => None, + _ => None, + } }, } } pub fn get_mut<'a>(&self, root: &'a mut Value) -> Option<&'a mut Value> { match *self { - Expression::Identifier(ref id) => match root.kind { - ValueKind::Table(ref mut map) => Some( - map.entry(id.clone()) - .or_insert_with(|| Value::new(None, ValueKind::Nil)), - ), + Expression::Identifier(ref id) => { + match root.kind { + ValueKind::Table(ref mut map) => map.get_mut(id), - _ => None, + _ => None, + } }, - Expression::Child(ref expr, ref key) => match expr.get_mut(root) { - Some(value) => match value.kind { + Expression::Child(ref expr, ref key) => { + match expr.get_mut(root) { + Some(value) => { + match value.kind { + ValueKind::Table(ref mut map) => map.get_mut(key), + + _ => None + } + }, + + _ => None, + } + }, + + Expression::Subscript(ref expr, index) => { + match expr.get_mut(root) { + Some(value) => match value.kind { + ValueKind::Array(ref mut array) => { + let index = sindex_to_uindex(index, array.len()); + + if index >= array.len() { + None + } else { + Some(&mut array[index]) + } + } + + _ => None, + }, + + _ => None, + } + }, + } + } + + pub fn get_mut_forcibly<'a>(&self, root: &'a mut Value) -> Option<&'a mut Value> { + match *self { + Expression::Identifier(ref id) => { + match root.kind { ValueKind::Table(ref mut map) => Some( - map.entry(key.clone()) + map.entry(id.clone()) .or_insert_with(|| Value::new(None, ValueKind::Nil)), ), - _ => { - *value = HashMap::::new().into(); + _ => None, + } + }, - if let ValueKind::Table(ref mut map) = value.kind { - Some( - map.entry(key.clone()) - .or_insert_with(|| Value::new(None, ValueKind::Nil)), - ) - } else { - unreachable!(); + Expression::Child(ref expr, ref key) => { + match expr.get_mut_forcibly(root) { + Some(value) => match value.kind { + ValueKind::Table(ref mut map) => Some( + map.entry(key.clone()) + .or_insert_with(|| Value::new(None, ValueKind::Nil)), + ), + + _ => { + *value = HashMap::::new().into(); + + if let ValueKind::Table(ref mut map) = value.kind { + Some( + map.entry(key.clone()) + .or_insert_with(|| Value::new(None, ValueKind::Nil)), + ) + } else { + unreachable!(); + } } - } - }, + }, - _ => None, + _ => None, + } }, - Expression::Subscript(ref expr, index) => match expr.get_mut(root) { - Some(value) => match value.kind { - ValueKind::Array(ref mut array) => { - let index = sindex_to_uindex(index, array.len()); - - if index >= array.len() { - array.resize((index + 1) as usize, Value::new(None, ValueKind::Nil)); + Expression::Subscript(ref expr, index) => { + let mut do_again = false; + match expr.get_mut_forcibly(root) { + Some(value) => { + match value.kind { + ValueKind::Array(_) => (), + _ => *value = Vec::::new().into() } - Some(&mut array[index]) - } + match value.kind { + ValueKind::Array(ref mut array) => { + let index = sindex_to_uindex(index, array.len()); - _ => None, - }, + if index >= array.len() { + array.resize((index + 1) as usize, Value::new(None, ValueKind::Nil)); + } + + Some(&mut array[index]) + } - _ => None, + _ => None + } + }, + _ => None + } }, } } @@ -171,7 +232,7 @@ impl Expression { } Expression::Child(ref expr, ref key) => { - if let Some(parent) = expr.get_mut(root) { + if let Some(parent) = expr.get_mut_forcibly(root) { match parent.kind { ValueKind::Table(_) => { Expression::Identifier(key.clone()).set(parent, value); @@ -188,11 +249,15 @@ impl Expression { } Expression::Subscript(ref expr, index) => { - if let Some(parent) = expr.get_mut(root) { + if let Some(parent) = expr.get_mut_forcibly(root) { + match parent.kind { + ValueKind::Array(_) => (), + _ => *parent = Vec::::new().into() + } + match parent.kind { ValueKind::Array(ref mut array) => { let uindex = sindex_to_uindex(index, array.len()); - if uindex >= array.len() { array.resize( (uindex + 1) as usize, @@ -203,13 +268,7 @@ impl Expression { array[uindex] = value.clone(); } - _ => { - // Didn't find an array ... - // Add an array and do this again - *parent = Vec::::new().into(); - - Expression::Subscript(expr.clone(), index).set(parent, value); - } + _ => () } } } diff --git a/src/path/parser.rs b/src/path/parser.rs index 7629193..3ec433e 100644 --- a/src/path/parser.rs +++ b/src/path/parser.rs @@ -101,6 +101,15 @@ mod test { let expected = Child(Box::new(Identifier("abcd".into())), "efgh".into()); assert_eq!(parsed, expected); + + let parsed: Expression = from_str("abcd.efgh.ijkl").unwrap(); + let expected = Child(Box::new( + Child(Box::new( + Identifier("abcd".into()) + ), "efgh".into()) + ), "ijkl".into()); + + assert_eq!(parsed, expected); } #[test] -- cgit v1.2.3 From 23ef2f466d972925ccae83a7394826457ebda27d Mon Sep 17 00:00:00 2001 From: XX Date: Sun, 8 Apr 2018 16:30:57 +0300 Subject: Add ConfigSerializer --- src/lib.rs | 4 ++++ src/ser.rs | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 187e2ca..15e7672 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,10 @@ #[macro_use] extern crate serde; +#[cfg(test)] +#[macro_use] +extern crate serde_derive; + extern crate nom; #[macro_use] diff --git a/src/ser.rs b/src/ser.rs index 7ea1a43..0366472 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -609,3 +609,24 @@ impl ser::SerializeStructVariant for StringKeySerializer { unreachable!() } } + +#[cfg(test)] +mod test { + use super::*; + use serde::Serialize; + + #[test] + fn test_struct() { + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct Test { + int: u32, + seq: Vec, + } + + let test = Test { int: 1, seq: vec!["a".to_string(), "b".to_string()] }; + let config = Config::try_from(&test).unwrap(); + + let actual: Test = config.try_into().unwrap(); + assert_eq!(test, actual); + } +} -- cgit v1.2.3