summaryrefslogtreecommitdiffstats
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
parente5a8323544ec98254d459ec6ecac43c162529390 (diff)
parent6c856712825f69993f285c951cc32edb3858b61a (diff)
Merge branch 'master' of https://github.com/limbo-rs/config-rs
-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
-rw-r--r--tests/set.rs16
7 files changed, 794 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);
+ }
+}
diff --git a/tests/set.rs b/tests/set.rs
index 0b0f1a3..577e074 100644
--- a/tests/set.rs
+++ b/tests/set.rs
@@ -29,6 +29,10 @@ fn test_set_scalar_default() {
fn test_set_scalar_path() {
let mut c = Config::default();
+ c.set("first.second.third", true).unwrap();
+
+ assert_eq!(c.get("first.second.third").ok(), Some(true));
+
c.merge(File::new("tests/Settings", FileFormat::Toml))
.unwrap();
@@ -43,6 +47,18 @@ fn test_set_scalar_path() {
fn test_set_arr_path() {
let mut c = Config::default();
+ c.set("items[0].name", "Ivan").unwrap();
+
+ assert_eq!(c.get("items[0].name").ok(), Some("Ivan".to_string()));
+
+ c.set("data[0].things[1].name", "foo").unwrap();
+ c.set("data[0].things[1].value", 42).unwrap();
+ c.set("data[1]", 0).unwrap();
+
+ assert_eq!(c.get("data[0].things[1].name").ok(), Some("foo".to_string()));
+ assert_eq!(c.get("data[0].things[1].value").ok(), Some(42));
+ assert_eq!(c.get("data[1]").ok(), Some(0));
+
c.merge(File::new("tests/Settings", FileFormat::Toml))
.unwrap();
'n1691' href='#n1691'>1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727