diff options
-rw-r--r-- | CHANGELOG.md | 6 | ||||
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | src/config.rs | 6 | ||||
-rw-r--r-- | src/de.rs | 2 | ||||
-rw-r--r-- | src/error.rs | 2 | ||||
-rw-r--r-- | src/file/format/hjson.rs | 2 | ||||
-rw-r--r-- | src/file/format/ini.rs | 6 | ||||
-rw-r--r-- | src/file/format/json.rs | 2 | ||||
-rw-r--r-- | src/file/format/toml.rs | 2 | ||||
-rw-r--r-- | src/file/format/yaml.rs | 2 | ||||
-rw-r--r-- | src/path/mod.rs | 2 | ||||
-rw-r--r-- | src/path/parser.rs | 91 | ||||
-rw-r--r-- | src/ser.rs | 10 | ||||
-rw-r--r-- | tests/errors.rs | 2 | ||||
-rw-r--r-- | tests/file_toml.rs | 2 | ||||
-rw-r--r-- | tests/get.rs | 1 | ||||
-rw-r--r-- | tests/set.rs | 11 |
17 files changed, 81 insertions, 72 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index d896fec..8b9abae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## 0.10.0 - 2019-12-07 + - Remove lowercasing of keys (unless the key is coming from an environment variable). + - Update nom to 5.x + ## 0.9.3 - 2019-05-09 - Support deserializing to a struct with `#[serde(default)]` [#106] - + [#106]: https://github.com/mehcode/config-rs/pull/106 ## 0.9.2 - 2019-01-03 @@ -1,6 +1,6 @@ [package] name = "config" -version = "0.9.2" +version = "0.10.0" description = "Layered configuration system for Rust applications." homepage = "https://github.com/mehcode/config-rs" repository = "https://github.com/mehcode/config-rs" @@ -23,7 +23,7 @@ ini = ["rust-ini"] [dependencies] lazy_static = "1.0" serde = "1.0.8" -nom = "4.0.0" +nom = "5.0.0" toml = { version = "0.5", optional = true } serde_json = { version = "1.0.2", optional = true } diff --git a/src/config.rs b/src/config.rs index 7e031d0..e54daa2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -125,7 +125,7 @@ impl Config { ConfigKind::Mutable { ref mut defaults, .. } => { - defaults.insert(key.to_lowercase().parse()?, value.into()); + defaults.insert(key.parse()?, value.into()); } ConfigKind::Frozen => return Err(ConfigError::Frozen), @@ -142,7 +142,7 @@ impl Config { ConfigKind::Mutable { ref mut overrides, .. } => { - overrides.insert(key.to_lowercase().parse()?, value.into()); + overrides.insert(key.parse()?, value.into()); } ConfigKind::Frozen => return Err(ConfigError::Frozen), @@ -153,7 +153,7 @@ impl Config { pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> { // Parse the key into a path expression - let expr: path::Expression = key.to_lowercase().parse()?; + let expr: path::Expression = key.parse()?; // Traverse the cache using the path to (possibly) retrieve a value let value = expr.get(&self.cache).cloned(); @@ -244,7 +244,7 @@ impl EnumAccess { fn variant_deserializer(&self, name: &String) -> Result<StrDeserializer> { self.variants .iter() - .find(|&s| s.to_lowercase() == name.to_lowercase()) + .find(|&s| s == name) .map(|&s| StrDeserializer(s)) .ok_or(self.no_constructor_error(name)) } diff --git a/src/error.rs b/src/error.rs index e305750..d7beeaf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -41,7 +41,7 @@ pub enum ConfigError { NotFound(String), /// Configuration path could not be parsed. - PathParse(nom::ErrorKind), + PathParse(nom::error::ErrorKind), /// Configuration could not be parsed from file. FileParse { diff --git a/src/file/format/hjson.rs b/src/file/format/hjson.rs index bb21e38..cb0a064 100644 --- a/src/file/format/hjson.rs +++ b/src/file/format/hjson.rs @@ -34,7 +34,7 @@ fn from_hjson_value(uri: Option<&String>, value: &serde_hjson::Value) -> Value { let mut m = HashMap::new(); for (key, value) in table { - m.insert(key.to_lowercase().clone(), from_hjson_value(uri, value)); + m.insert(key.clone(), from_hjson_value(uri, value)); } Value::new(uri, ValueKind::Table(m)) diff --git a/src/file/format/ini.rs b/src/file/format/ini.rs index b4b4ada..845de3a 100644 --- a/src/file/format/ini.rs +++ b/src/file/format/ini.rs @@ -16,19 +16,19 @@ pub fn parse( let mut sec_map: HashMap<String, Value> = HashMap::new(); for (k, v) in prop.iter() { sec_map.insert( - k.to_lowercase().clone(), + k.clone(), Value::new(uri, ValueKind::String(v.clone())), ); } map.insert( - sec.to_lowercase().clone(), + sec.clone(), Value::new(uri, ValueKind::Table(sec_map)), ); } None => { for (k, v) in prop.iter() { map.insert( - k.to_lowercase().clone(), + k.clone(), Value::new(uri, ValueKind::String(v.clone())), ); } diff --git a/src/file/format/json.rs b/src/file/format/json.rs index caf62f5..87240a3 100644 --- a/src/file/format/json.rs +++ b/src/file/format/json.rs @@ -36,7 +36,7 @@ fn from_json_value(uri: Option<&String>, value: &serde_json::Value) -> Value { let mut m = HashMap::new(); for (key, value) in table { - m.insert(key.to_lowercase().clone(), from_json_value(uri, value)); + m.insert(key.clone(), from_json_value(uri, value)); } Value::new(uri, ValueKind::Table(m)) diff --git a/src/file/format/toml.rs b/src/file/format/toml.rs index da7782f..26dcb2a 100644 --- a/src/file/format/toml.rs +++ b/src/file/format/toml.rs @@ -29,7 +29,7 @@ fn from_toml_value(uri: Option<&String>, value: &toml::Value) -> Value { let mut m = HashMap::new(); for (key, value) in table { - m.insert(key.to_lowercase().clone(), from_toml_value(uri, value)); + m.insert(key.clone(), from_toml_value(uri, value)); } Value::new(uri, m) diff --git a/src/file/format/yaml.rs b/src/file/format/yaml.rs index 5ec8ca6..c2b26cb 100644 --- a/src/file/format/yaml.rs +++ b/src/file/format/yaml.rs @@ -42,7 +42,7 @@ fn from_yaml_value(uri: Option<&String>, value: &yaml::Yaml) -> Value { let mut m = HashMap::new(); for (key, value) in table { if let Some(k) = key.as_str() { - m.insert(k.to_lowercase().to_owned(), from_yaml_value(uri, value)); + m.insert(k.to_owned(), from_yaml_value(uri, value)); } // TODO: should we do anything for non-string keys? } diff --git a/src/path/mod.rs b/src/path/mod.rs index 7fe6e44..f63deee 100644 --- a/src/path/mod.rs +++ b/src/path/mod.rs @@ -1,5 +1,5 @@ use error::*; -use nom::ErrorKind; +use nom::error::ErrorKind; use std::collections::HashMap; use std::str::FromStr; use value::{Value, ValueKind}; diff --git a/src/path/parser.rs b/src/path/parser.rs index a1660ca..d783f3e 100644 --- a/src/path/parser.rs +++ b/src/path/parser.rs @@ -1,53 +1,53 @@ use super::Expression; -use nom::types::CompleteStr; -use nom::{digit, ErrorKind, IResult}; +use nom::{ + IResult, Err, + error::ErrorKind, + bytes::complete::{is_a, tag}, + character::complete::{char, digit1, space0}, + sequence::{delimited, pair, preceded}, + branch::alt, + combinator::{map, map_res, opt, recognize}, +}; use std::str::{from_utf8, FromStr}; -named!(raw_ident<CompleteStr, String>, - map!(is_a!( +fn raw_ident(i: &str) -> IResult<&str, String> { + map(is_a( "abcdefghijklmnopqrstuvwxyz \ ABCDEFGHIJKLMNOPQRSTUVWXYZ \ 0123456789 \ _-" - ), |s: CompleteStr| { - s.to_string() - }) -); - -named!(integer<CompleteStr, isize>, - map_res!( - ws!(digit), - |s: CompleteStr| { - s.parse() - } - ) -); - -named!(ident<CompleteStr, Expression>, map!(raw_ident, Expression::Identifier)); - -#[allow(cyclomatic_complexity)] -fn postfix(expr: Expression) -> Box<Fn(CompleteStr) -> IResult<CompleteStr, Expression>> { - Box::new(move |i: CompleteStr| { - alt!( - i, - do_parse!(tag!(".") >> id: raw_ident >> (Expression::Child(Box::new(expr.clone()), id))) - | delimited!( - char!('['), - do_parse!( - negative: opt!(tag!("-")) >> num: integer - >> (Expression::Subscript( - Box::new(expr.clone()), - num * (if negative.is_none() { 1 } else { -1 }), - )) - ), - char!(']') - ) - ) - }) + ), |s:&str| s.to_string())(i) +} + +fn integer(i: &str) -> IResult<&str, isize> { + map_res( + delimited( + space0, + recognize(pair(opt(tag("-")), digit1)), + space0 + ), + FromStr::from_str + )(i) +} + +fn ident(i: &str) -> IResult<&str, Expression> { + map(raw_ident, Expression::Identifier)(i) +} + +fn postfix<'a>(expr: Expression) -> impl Fn(&'a str) -> IResult<&'a str, Expression> { + let e2 = expr.clone(); + let child = map(preceded(tag("."), raw_ident), move |id| Expression::Child(Box::new(expr.clone()), id)); + + let subscript = map(delimited(char('['), integer, char(']')), move |num| Expression::Subscript(Box::new(e2.clone()), num)); + + alt(( + child, + subscript + )) } pub fn from_str(input: &str) -> Result<Expression, ErrorKind> { - match ident(CompleteStr(input)) { + match ident(input) { Ok((mut rem, mut expr)) => { while !rem.is_empty() { match postfix(expr)(rem) { @@ -58,7 +58,7 @@ pub fn from_str(input: &str) -> Result<Expression, ErrorKind> { // Forward Incomplete and Error result => { - return result.map(|(_, o)| o).map_err(|e| e.into_error_kind()); + return result.map(|(_, o)| o).map_err(to_error_kind); } } } @@ -67,10 +67,17 @@ pub fn from_str(input: &str) -> Result<Expression, ErrorKind> { } // Forward Incomplete and Error - result => result.map(|(_, o)| o).map_err(|e| e.into_error_kind()), + result => result.map(|(_, o)| o).map_err(to_error_kind), } } +pub fn to_error_kind(e: Err<(&str, ErrorKind)>) -> ErrorKind { + match e { + Err::Incomplete(_) => ErrorKind::Complete, + Err::Failure((_, e)) | Err::Error((_, e)) => e, + } +} + #[cfg(test)] mod test { use super::Expression::*; @@ -186,7 +186,7 @@ impl<'a> ser::Serializer for &'a mut ConfigSerializer { _variant_index: u32, variant: &'static str, ) -> Result<Self::Ok> { - self.serialize_str(&variant.to_lowercase()) + self.serialize_str(&variant) } fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Self::Ok> @@ -206,7 +206,7 @@ impl<'a> ser::Serializer for &'a mut ConfigSerializer { where T: ?Sized + ser::Serialize, { - self.push_key(&variant.to_lowercase()); + self.push_key(&variant); value.serialize(&mut *self)?; self.pop_key(); Ok(()) @@ -235,7 +235,7 @@ impl<'a> ser::Serializer for &'a mut ConfigSerializer { variant: &'static str, _len: usize, ) -> Result<Self::SerializeTupleVariant> { - self.push_key(&variant.to_lowercase()); + self.push_key(&variant); Ok(self) } @@ -254,7 +254,7 @@ impl<'a> ser::Serializer for &'a mut ConfigSerializer { variant: &'static str, len: usize, ) -> Result<Self::SerializeStructVariant> { - self.push_key(&variant.to_lowercase()); + self.push_key(&variant); Ok(self) } } @@ -493,7 +493,7 @@ impl ser::Serializer for StringKeySerializer { _variant_index: u32, variant: &str, ) -> Result<Self::Ok> { - Ok(variant.to_lowercase()) + Ok(variant.to_string()) } fn serialize_newtype_struct<T>(self, _name: &str, value: &T) -> Result<Self::Ok> diff --git a/tests/errors.rs b/tests/errors.rs index d1e7afc..5f4a1a5 100644 --- a/tests/errors.rs +++ b/tests/errors.rs @@ -23,7 +23,7 @@ fn test_error_parse() { assert!(res.is_err()); assert_eq!( res.unwrap_err().to_string(), - "failed to parse datetime for key `error` in tests/Settings-invalid.toml".to_string() + "failed to parse datetime for key `error` at line 2 column 9 in tests/Settings-invalid.toml".to_string() ); } diff --git a/tests/file_toml.rs b/tests/file_toml.rs index 13e1d8e..d1ae5db 100644 --- a/tests/file_toml.rs +++ b/tests/file_toml.rs @@ -82,6 +82,6 @@ fn test_error_parse() { assert!(res.is_err()); assert_eq!( res.unwrap_err().to_string(), - "failed to parse datetime for key `error` in tests/Settings-invalid.toml".to_string() + "failed to parse datetime for key `error` at line 2 column 9 in tests/Settings-invalid.toml".to_string() ); } diff --git a/tests/get.rs b/tests/get.rs index acc823d..a5fea69 100644 --- a/tests/get.rs +++ b/tests/get.rs @@ -206,6 +206,7 @@ fn test_struct_array() { #[test] fn test_enum() { #[derive(Debug, Deserialize, PartialEq)] + #[serde(rename_all = "lowercase")] enum Diode { Off, Brightness(i32), diff --git a/tests/set.rs b/tests/set.rs index bd439a0..ac8d5c9 100644 --- a/tests/set.rs +++ b/tests/set.rs @@ -82,15 +82,12 @@ fn test_set_arr_path() { fn test_set_capital() { let mut c = Config::default(); - c.set_default("tHiS", false).unwrap(); - c.set("THAT", true).unwrap(); - c.merge(File::from_str("{\"loGleVel\": 5}", FileFormat::Json)) + c.set_default("this", false).unwrap(); + c.set("ThAt", true).unwrap(); + c.merge(File::from_str("{\"logLevel\": 5}", FileFormat::Json)) .unwrap(); assert_eq!(c.get("this").ok(), Some(false)); - assert_eq!(c.get("ThIs").ok(), Some(false)); - assert_eq!(c.get("that").ok(), Some(true)); - assert_eq!(c.get("THAT").ok(), Some(true)); + assert_eq!(c.get("ThAt").ok(), Some(true)); assert_eq!(c.get("logLevel").ok(), Some(5)); - assert_eq!(c.get("loglevel").ok(), Some(5)); } |