summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRyan Leckey <leckey.ryan@gmail.com>2018-07-02 15:06:21 -0700
committerRyan Leckey <leckey.ryan@gmail.com>2018-07-02 15:06:21 -0700
commitb8a1d8a65defb08c501df83b464a55f270765876 (patch)
tree3668b5983885018401d48e2b4d233ab678f71f8a /src
parente5a8323544ec98254d459ec6ecac43c162529390 (diff)
parent6c856712825f69993f285c951cc32edb3858b61a (diff)
Merge branch 'master' of https://github.com/limbo-rs/config-rs
Diffstat (limited to 'src')
-rw-r--r--src/config.rs11
-rw-r--r--src/error.rs7
-rw-r--r--src/lib.rs5
-rw-r--r--src/path/mod.rs171
-rw-r--r--src/path/parser.rs9
-rw-r--r--src/ser.rs632
6 files changed, 778 insertions, 57 deletions
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<T: Serialize>(from: &T) -> Result<Self> {
+ 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<T> {
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<T: fmt::Display>(msg: T) -> Self {
+ ConfigError::Message(msg.to_string())
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 6178375..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]
@@ -46,6 +50,7 @@ extern crate serde_hjson;
mod error;
mod value;
mod de;
+mod ser;
mod path;
mod source;
mod config;
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::<String, Value>::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::<String, Value>::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::<Value>::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::<Value>::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::<Value>::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]
diff --git a/src/ser.rs b/src/ser.rs
new file mode 100644
index 0000000..0366472
--- /dev/null
+++ b/src/ser.rs
@@ -0,0 +1,632 @@
+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<usize>)>,
+ pub output: Config,
+}
+
+impl ConfigSerializer {
+ fn serialize_primitive<T>(&mut self, value: T) -> Result<()>
+ where T: Into<Value> + 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<usize>)> {
+ 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<usize>)> {
+ 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::Ok> {
+ self.serialize_primitive(v)
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
+ self.serialize_i64(v as i64)
+ }
+
+ fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
+ self.serialize_primitive(v)
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
+ self.serialize_u64(v as u64)
+ }
+
+ fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
+ self.serialize_u64(v as u64)
+ }
+
+ fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
+ self.serialize_u64(v as u64)
+ }
+
+ fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
+ 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::Ok> {
+ self.serialize_f64(v as f64)
+ }
+
+ fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
+ self.serialize_primitive(v)
+ }
+
+ fn serialize_char(self, v: char) -> Result<Self::Ok> {
+ self.serialize_primitive(v.to_string())
+ }
+
+ fn serialize_str(self, v: &str) -> Result<Self::Ok> {
+ self.serialize_primitive(v.to_string())
+ }
+
+ fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
+ 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::Ok> {
+ self.serialize_unit()
+ }
+
+ fn serialize_some<T>(self, value: &T) -> Result<Self::Ok>
+ where T: ?Sized + ser::Serialize
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok> {
+ self.serialize_primitive(Value::from(ValueKind::Nil))
+ }
+
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
+ self.serialize_unit()
+ }
+
+ fn serialize_unit_variant(self, _name: &'static str, _variant_index: u32, variant: &'static str)
+ -> Result<Self::Ok>
+ {
+ self.serialize_str(&variant.to_lowercase())
+ }
+
+ fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Self::Ok>
+ where T: ?Sized + ser::Serialize
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T>(self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T)
+ -> Result<Self::Ok>
+ 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<usize>) -> Result<Self::SerializeSeq> {
+ Ok(self)
+ }
+
+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_tuple_struct(self, _name: &'static str, len: usize)
+ -> Result<Self::SerializeTupleStruct>
+ {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_tuple_variant(self, name: &'static str, _variant_index: u32, variant: &'static str, _len: usize)
+ -> Result<Self::SerializeTupleVariant>
+ {
+ self.push_key(&variant.to_lowercase());
+ Ok(self)
+ }
+
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
+ Ok(self)
+ }
+
+ fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
+ self.serialize_map(Some(len))
+ }
+
+ fn serialize_struct_variant(self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize)
+ -> Result<Self::SerializeStructVariant>
+ {
+ self.push_key(&variant.to_lowercase());
+ Ok(self)
+ }
+}
+
+impl<'a> ser::SerializeSeq for &'a mut ConfigSerializer {
+ type Ok = ();
+ type Error = ConfigError;
+
+ fn serialize_element<T>(&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::Ok> {
+ Ok(())
+ }
+}
+
+impl<'a> ser::SerializeTuple for &'a mut ConfigSerializer {
+ type Ok = ();
+ type Error = ConfigError;
+
+ fn serialize_element<T>(&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::Ok> {
+ Ok(())
+ }
+}
+
+impl<'a> ser::SerializeTupleStruct for &'a mut ConfigSerializer {
+ type Ok = ();
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&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::Ok> {
+ Ok(())
+ }
+}
+
+impl<'a> ser::SerializeTupleVariant for &'a mut ConfigSerializer {
+ type Ok = ();
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&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::Ok> {
+ self.pop_key();
+ Ok(())
+ }
+}
+
+impl<'a> ser::SerializeMap for &'a mut ConfigSerializer {
+ type Ok = ();
+ type Error = ConfigError;
+
+ fn serialize_key<T>(&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<T>(&mut self, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ value.serialize(&mut **self)?;
+ self.pop_key();
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ Ok(())
+ }
+}
+
+impl<'a> ser::SerializeStruct for &'a mut ConfigSerializer {
+ type Ok = ();
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&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::Ok> {
+ Ok(())
+ }
+}
+
+impl<'a> ser::SerializeStructVariant for &'a mut ConfigSerializer {
+ type Ok = ();
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&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::Ok> {
+ 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<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_char(self, v: char) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_str(self, v: &str) -> Result<Self::Ok> {
+ Ok(v.to_string())
+ }
+
+ fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
+ Ok(String::from_utf8_lossy(v).to_string())
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok> {
+ self.serialize_unit()
+ }
+
+ fn serialize_some<T>(self, value: &T) -> Result<Self::Ok>
+ where T: ?Sized + ser::Serialize
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok> {
+ Ok(String::new())
+ }
+
+ fn serialize_unit_struct(self, _name: &str) -> Result<Self::Ok> {
+ self.serialize_unit()
+ }
+
+ fn serialize_unit_variant(self, _name: &str, _variant_index: u32, variant: &str) -> Result<Self::Ok> {
+ Ok(variant.to_lowercase())
+ }
+
+ fn serialize_newtype_struct<T>(self, _name: &str, value: &T) -> Result<Self::Ok>
+ where T: ?Sized + ser::Serialize
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T>(self, _name: &str, _variant_index: u32, _variant: &str, value: &T)
+ -> Result<Self::Ok>
+ where T: ?Sized + ser::Serialize
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
+ Err(ConfigError::Message("seq can't serialize to string key".to_string()))
+ }
+
+ fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
+ Err(ConfigError::Message("tuple can't serialize to string key".to_string()))
+ }
+
+ fn serialize_tuple_struct(self, name: &str, _len: usize) -> Result<Self::SerializeTupleStruct> {
+ 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<Self::SerializeTupleVariant>
+ {
+ Err(ConfigError::Message(format!("tuple variant {}::{} can't serialize to string key", name, variant)))
+ }
+
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
+ Err(ConfigError::Message("map can't serialize to string key".to_string()))
+ }
+
+ fn serialize_struct(self, name: &str, _len: usize) -> Result<Self::SerializeStruct> {
+ 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<Self::SerializeStructVariant>
+ {
+ 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<T>(&mut self, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ unreachable!()
+ }
+}
+
+impl ser::SerializeTuple for StringKeySerializer {
+ type Ok = String;
+ type Error = ConfigError;
+
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ unreachable!()
+ }
+}
+
+impl ser::SerializeTupleStruct for StringKeySerializer {
+ type Ok = String;
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ unreachable!()
+ }
+}
+
+impl ser::SerializeTupleVariant for StringKeySerializer {
+ type Ok = String;
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ unreachable!()
+ }
+}
+
+impl ser::SerializeMap for StringKeySerializer {
+ type Ok = String;
+ type Error = ConfigError;
+
+ fn serialize_key<T>(&mut self, key: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn serialize_value<T>(&mut self, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ unreachable!()
+ }
+}
+
+impl ser::SerializeStruct for StringKeySerializer {
+ type Ok = String;
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ unreachable!()
+ }
+}
+
+impl ser::SerializeStructVariant for StringKeySerializer {
+ type Ok = String;
+ type Error = ConfigError;
+
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where T: ?Sized + ser::Serialize
+ {
+ unreachable!()
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ 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<String>,
+ }
+
+ 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);
+ }
+}