summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--Cargo.toml4
-rw-r--r--src/config.rs6
-rw-r--r--src/de.rs2
-rw-r--r--src/error.rs2
-rw-r--r--src/file/format/hjson.rs2
-rw-r--r--src/file/format/ini.rs6
-rw-r--r--src/file/format/json.rs2
-rw-r--r--src/file/format/toml.rs2
-rw-r--r--src/file/format/yaml.rs2
-rw-r--r--src/path/mod.rs2
-rw-r--r--src/path/parser.rs91
-rw-r--r--src/ser.rs10
-rw-r--r--tests/errors.rs2
-rw-r--r--tests/file_toml.rs2
-rw-r--r--tests/get.rs1
-rw-r--r--tests/set.rs11
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
diff --git a/Cargo.toml b/Cargo.toml
index d6360fc..ef39903 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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();
diff --git a/src/de.rs b/src/de.rs
index 6cdd689..3c9e210 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -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::*;
diff --git a/src/ser.rs b/src/ser.rs
index b4c1628..b5b19ed 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -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));
}