summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.rs11
-rw-r--r--src/de.rs9
-rw-r--r--src/env.rs36
-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
-rw-r--r--src/value.rs6
-rw-r--r--tests/Settings.toml3
-rw-r--r--tests/env.rs63
-rw-r--r--tests/file_hjson.rs2
-rw-r--r--tests/file_json.rs2
-rw-r--r--tests/file_toml.rs12
-rw-r--r--tests/file_yaml.rs2
-rw-r--r--tests/get.rs4
-rw-r--r--tests/set.rs16
17 files changed, 907 insertions, 83 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/de.rs b/src/de.rs
index 3e86bd2..89c21e0 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -224,9 +224,16 @@ impl<'de> de::Deserializer<'de> for Value {
}
}
+ fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>
+ {
+ visitor.visit_newtype_struct(self)
+ }
+
forward_to_deserialize_any! {
char seq
- bytes byte_buf map struct unit enum newtype_struct
+ bytes byte_buf map struct unit enum
identifier ignored_any unit_struct tuple_struct tuple
}
}
diff --git a/src/env.rs b/src/env.rs
index aec4de4..b26dc56 100644
--- a/src/env.rs
+++ b/src/env.rs
@@ -9,19 +9,16 @@ pub struct Environment {
/// Optional prefix that will limit access to the environment to only keys that
/// begin with the defined prefix.
///
- /// A prefix, followed by `_` (the seperator),
- /// is tested to be present on each key before its considered
+ /// A prefix with a separator of `_` is tested to be present on each key before its considered
/// to be part of the source environment.
///
/// For example, the key `CONFIG_DEBUG` would become `DEBUG` with a prefix of `config`.
prefix: Option<String>,
- /// The character sequence that separates each key segment in an environment key pattern.
+ /// Optional character sequence that separates each key segment in an environment key pattern.
/// Consider a nested configuration such as `redis.password`, a separator of `_` would allow
/// an environment key of `REDIS_PASSWORD` to match.
- ///
- /// The default separator is `_`.
- separator: String,
+ separator: Option<String>,
}
impl Environment {
@@ -36,13 +33,13 @@ impl Environment {
}
}
- pub fn prefix(&mut self, s: String) -> &mut Self {
- self.prefix = s.into();
+ pub fn prefix(&mut self, s: &str) -> &mut Self {
+ self.prefix = Some(s.into());
self
}
- pub fn separator(&mut self, s: String) -> &mut Self {
- self.separator = s;
+ pub fn separator(&mut self, s: &str) -> &mut Self {
+ self.separator = Some(s.into());
self
}
}
@@ -51,7 +48,7 @@ impl Default for Environment {
fn default() -> Environment {
Environment {
prefix: None,
- separator: "_".into(),
+ separator: None,
}
}
}
@@ -65,9 +62,14 @@ impl Source for Environment {
let mut m = HashMap::new();
let uri: String = "the environment".into();
- // Define a prefiux pattern to test and exclude from keys
+ let separator = match self.separator {
+ Some(ref separator) => separator,
+ _ => ""
+ };
+
+ // Define a prefix pattern to test and exclude from keys
let prefix_pattern = match self.prefix {
- Some(ref prefix) => Some(prefix.clone() + &self.separator),
+ Some(ref prefix) => Some(prefix.clone() + "_"),
_ => None,
};
@@ -76,7 +78,7 @@ impl Source for Environment {
// Check for prefix
if let Some(ref prefix_pattern) = prefix_pattern {
- if key.to_lowercase().starts_with(prefix_pattern) {
+ if key.to_lowercase().starts_with(&prefix_pattern.to_lowercase()) {
// Remove this prefix from the key
key = key[prefix_pattern.len()..].to_string();
} else {
@@ -85,8 +87,10 @@ impl Source for Environment {
}
}
- // Replace `separator` with `.`
- key = key.replace(&self.separator, ".");
+ // If separator is given replace with `.`
+ if !separator.is_empty() {
+ key = key.replace(separator, ".");
+ }
m.insert(
key.to_lowercase(),
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 61fa217..b998ee1 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, _