Skip to content

Commit b03a0f5

Browse files
authored
Merge pull request #613 from epage/lower
Revert Fix uppercase lowercase isses (#354, #429)
2 parents 943987c + 51eacda commit b03a0f5

File tree

16 files changed

+185
-127
lines changed

16 files changed

+185
-127
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@
2323
[RON]: https://github.com/ron-rs/ron
2424
[JSON5]: https://github.com/callum-oakley/json5-rs
2525

26-
Please note this library
27-
28-
- can not be used to write changed configuration values back to the configuration file(s)!
29-
- Is case insensitive and all the keys are converted to lowercase internally
26+
Please note that this library can not be used to write changed configuration
27+
values back to the configuration file(s)!
3028

3129
## Usage
3230

src/config.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,7 @@ impl Config {
110110
where
111111
T: Into<Value>,
112112
{
113-
self.defaults
114-
.insert(key.to_lowercase().as_str().parse()?, value.into());
113+
self.defaults.insert(key.parse()?, value.into());
115114

116115
#[allow(deprecated)]
117116
self.refresh()
@@ -130,16 +129,15 @@ impl Config {
130129
where
131130
T: Into<Value>,
132131
{
133-
self.overrides
134-
.insert(key.to_lowercase().as_str().parse()?, value.into());
132+
self.overrides.insert(key.parse()?, value.into());
135133

136134
#[allow(deprecated)]
137135
self.refresh()
138136
}
139137

140138
#[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
141139
pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> {
142-
let expr: path::Expression = key.to_lowercase().as_str().parse()?;
140+
let expr: path::Expression = key.parse()?;
143141

144142
// Traverse the cache using the path to (possibly) retrieve a value
145143
if let Some(ref mut val) = expr.get_mut(&mut self.cache) {
@@ -151,8 +149,6 @@ impl Config {
151149
}
152150

153151
fn get_value(&self, key: &str) -> Result<Value> {
154-
let k = key.to_lowercase();
155-
let key = k.as_str();
156152
// Parse the key into a path expression
157153
let expr: path::Expression = key.parse()?;
158154

src/de.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ impl EnumAccess {
272272
fn variant_deserializer(&self, name: &str) -> Result<StrDeserializer<'_>> {
273273
self.variants
274274
.iter()
275-
.find(|&&s| s.to_lowercase() == name.to_lowercase()) // changing to lowercase will enable deserialization of lowercase values to enums
275+
.find(|&&s| s == name)
276276
.map(|&s| StrDeserializer(s))
277277
.ok_or_else(|| self.no_constructor_error(name))
278278
}

src/env.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@ impl Environment {
155155
/// To switch the default type back to type Strings you need to provide the keys which should be [`Vec<String>`] using this function.
156156
pub fn with_list_parse_key(mut self, key: &str) -> Self {
157157
if self.list_parse_keys.is_none() {
158-
self.list_parse_keys = Some(vec![key.to_lowercase()]);
158+
self.list_parse_keys = Some(vec![key.into()]);
159159
} else {
160160
self.list_parse_keys = self.list_parse_keys.map(|mut keys| {
161-
keys.push(key.to_lowercase());
161+
keys.push(key.into());
162162
keys
163163
});
164164
}
@@ -289,9 +289,6 @@ impl Source for Environment {
289289
ValueKind::Float(parsed)
290290
} else if let Some(separator) = &self.list_separator {
291291
if let Some(keys) = &self.list_parse_keys {
292-
#[cfg(feature = "convert-case")]
293-
let key = key.to_lowercase();
294-
295292
if keys.contains(&key) {
296293
let v: Vec<Value> = value
297294
.split(separator)

src/path/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl Expression {
120120
match *self {
121121
Self::Identifier(ref id) => match root.kind {
122122
ValueKind::Table(ref mut map) => Some(
123-
map.entry(id.to_lowercase())
123+
map.entry(id.clone())
124124
.or_insert_with(|| Value::new(None, ValueKind::Nil)),
125125
),
126126

@@ -131,15 +131,15 @@ impl Expression {
131131
Some(value) => {
132132
if let ValueKind::Table(ref mut map) = value.kind {
133133
Some(
134-
map.entry(key.to_lowercase())
134+
map.entry(key.clone())
135135
.or_insert_with(|| Value::new(None, ValueKind::Nil)),
136136
)
137137
} else {
138138
*value = Map::<String, Value>::new().into();
139139

140140
if let ValueKind::Table(ref mut map) = value.kind {
141141
Some(
142-
map.entry(key.to_lowercase())
142+
map.entry(key.clone())
143143
.or_insert_with(|| Value::new(None, ValueKind::Nil)),
144144
)
145145
} else {
@@ -193,25 +193,25 @@ impl Expression {
193193
ValueKind::Table(ref incoming_map) => {
194194
// Pull out another table
195195
let target = if let ValueKind::Table(ref mut map) = root.kind {
196-
map.entry(id.to_lowercase())
196+
map.entry(id.clone())
197197
.or_insert_with(|| Map::<String, Value>::new().into())
198198
} else {
199199
unreachable!();
200200
};
201201

202202
// Continue the deep merge
203203
for (key, val) in incoming_map {
204-
Self::Identifier(key.to_lowercase()).set(target, val.clone());
204+
Self::Identifier(key.clone()).set(target, val.clone());
205205
}
206206
}
207207

208208
_ => {
209209
if let ValueKind::Table(ref mut map) = root.kind {
210210
// Just do a simple set
211-
if let Some(existing) = map.get_mut(&id.to_lowercase()) {
211+
if let Some(existing) = map.get_mut(id) {
212212
*existing = value;
213213
} else {
214-
map.insert(id.to_lowercase(), value);
214+
map.insert(id.clone(), value);
215215
}
216216
}
217217
}
@@ -224,7 +224,7 @@ impl Expression {
224224
// Didn't find a table. Oh well. Make a table and do this anyway
225225
*parent = Map::<String, Value>::new().into();
226226
}
227-
Self::Identifier(key.to_lowercase()).set(parent, value);
227+
Self::Identifier(key.clone()).set(parent, value);
228228
}
229229
}
230230

tests/testsuite/case.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use serde_derive::Deserialize;
2+
3+
use config::{Config, File, FileFormat};
4+
5+
#[test]
6+
#[cfg(feature = "json")]
7+
fn respect_field_case() {
8+
#[derive(Deserialize, Debug)]
9+
#[allow(non_snake_case)]
10+
#[allow(dead_code)]
11+
struct Kafka {
12+
broker: String,
13+
topic: String,
14+
pollSleep: u64, //<---
15+
}
16+
17+
let c = Config::builder()
18+
.add_source(File::from_str(
19+
r#"
20+
{
21+
"broker": "localhost:29092",
22+
"topic": "rust",
23+
"pollSleep": 1000
24+
}
25+
"#,
26+
FileFormat::Json,
27+
))
28+
.build()
29+
.unwrap();
30+
31+
c.try_deserialize::<Kafka>().unwrap();
32+
}
33+
34+
#[test]
35+
#[cfg(feature = "json")]
36+
fn respect_renamed_field() {
37+
#[derive(Deserialize, Debug)]
38+
#[allow(dead_code)]
39+
struct MyConfig {
40+
#[serde(rename = "FooBar")]
41+
foo_bar: String,
42+
}
43+
44+
let c = Config::builder()
45+
.add_source(File::from_str(
46+
r#"
47+
{
48+
"FooBar": "Hello, world!"
49+
}
50+
"#,
51+
FileFormat::Json,
52+
))
53+
.build()
54+
.unwrap();
55+
56+
c.try_deserialize::<MyConfig>().unwrap();
57+
}
58+
59+
#[test]
60+
#[cfg(feature = "json")]
61+
fn respect_path_case() {
62+
let c = Config::builder()
63+
.add_source(File::from_str(
64+
r#"
65+
{
66+
"Student": [
67+
{ "Name": "1" },
68+
{ "Name": "2" }
69+
]
70+
}
71+
"#,
72+
FileFormat::Json,
73+
))
74+
.build()
75+
.unwrap();
76+
77+
c.get_string("Student[0].Name").unwrap();
78+
}

tests/testsuite/env.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
use config::{Config, Environment, Source};
21
use serde_derive::Deserialize;
2+
use snapbox::{assert_data_eq, str};
3+
4+
use config::{Config, Environment, Source};
35

46
/// Reminder that tests using env variables need to use different env variable names, since
57
/// tests can be run in parallel
@@ -474,11 +476,13 @@ fn test_parse_string_and_list_ignore_list_parse_key_case() {
474476
// using a struct in an enum here to make serde use `deserialize_any`
475477
#[derive(Deserialize, Debug)]
476478
#[serde(tag = "tag")]
479+
#[allow(dead_code)]
477480
enum TestStringEnum {
478481
String(TestString),
479482
}
480483

481484
#[derive(Deserialize, Debug)]
485+
#[allow(dead_code)]
482486
struct TestString {
483487
string_val: String,
484488
string_list: Vec<String>,
@@ -503,20 +507,13 @@ fn test_parse_string_and_list_ignore_list_parse_key_case() {
503507
.build()
504508
.unwrap();
505509

506-
let config: TestStringEnum = config.try_deserialize().unwrap();
510+
let res = config.try_deserialize::<TestStringEnum>();
507511

508-
match config {
509-
TestStringEnum::String(TestString {
510-
string_val,
511-
string_list,
512-
}) => {
513-
assert_eq!(String::from("test,string"), string_val);
514-
assert_eq!(
515-
vec![String::from("test"), String::from("string")],
516-
string_list
517-
);
518-
}
519-
}
512+
assert!(res.is_err());
513+
assert_data_eq!(
514+
res.unwrap_err().to_string(),
515+
str![[r#"invalid type: string "test,string", expected a sequence"#]]
516+
);
520517
},
521518
);
522519
}

tests/testsuite/file_ini.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ rating = 4.5
121121
match cap_settings {
122122
Ok(v) => {
123123
// this assertion will ensure that the map has only lowercase keys
124-
assert_ne!(v.FOO, "FOO should be overridden");
124+
assert_eq!(v.FOO, "FOO should be overridden");
125125
assert_eq!(
126126
lower_settings.foo,
127127
"I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_owned()
@@ -198,11 +198,12 @@ bar = "bar is a lowercase param"
198198
.add_source(config::Environment::with_prefix("APPS").separator("_"))
199199
.build()
200200
.unwrap();
201-
let val: EnumSettings = cfg.try_deserialize().unwrap();
202201

203-
assert_eq!(
204-
val,
205-
EnumSettings::Bar("I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_owned())
202+
let param = cfg.try_deserialize::<EnumSettings>();
203+
assert!(param.is_err());
204+
assert_data_eq!(
205+
param.unwrap_err().to_string(),
206+
str!["enum EnumSettings does not have variant constructor bar"]
206207
);
207208
}
208209

@@ -226,11 +227,11 @@ bar = "bar is a lowercase param"
226227
.build()
227228
.unwrap();
228229

229-
let param: EnumSettings = cfg.try_deserialize().unwrap();
230-
231-
assert_eq!(
232-
param,
233-
EnumSettings::Bar("I have been overridden_with_lower_case".to_owned())
230+
let param = cfg.try_deserialize::<EnumSettings>();
231+
assert!(param.is_err());
232+
assert_data_eq!(
233+
param.unwrap_err().to_string(),
234+
str!["enum EnumSettings does not have variant constructor bar"]
234235
);
235236
}
236237

tests/testsuite/file_json.rs

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -115,27 +115,6 @@ fn test_error_parse() {
115115
);
116116
}
117117

118-
#[test]
119-
fn test_json_vec() {
120-
let c = Config::builder()
121-
.add_source(File::from_str(
122-
r#"
123-
{
124-
"WASTE": ["example_dir1", "example_dir2"]
125-
}
126-
"#,
127-
FileFormat::Json,
128-
))
129-
.build()
130-
.unwrap();
131-
132-
let v = c.get_array("WASTE").unwrap();
133-
let mut vi = v.into_iter();
134-
assert_eq!(vi.next().unwrap().into_string().unwrap(), "example_dir1");
135-
assert_eq!(vi.next().unwrap().into_string().unwrap(), "example_dir2");
136-
assert!(vi.next().is_none());
137-
}
138-
139118
#[test]
140119
fn test_override_uppercase_value_for_struct() {
141120
#[derive(Debug, Deserialize, PartialEq)]
@@ -189,7 +168,7 @@ fn test_override_uppercase_value_for_struct() {
189168
match cap_settings {
190169
Ok(v) => {
191170
// this assertion will ensure that the map has only lowercase keys
192-
assert_ne!(v.FOO, "FOO should be overridden");
171+
assert_eq!(v.FOO, "FOO should be overridden");
193172
assert_eq!(
194173
lower_settings.foo,
195174
"I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_owned()
@@ -279,11 +258,12 @@ fn test_override_uppercase_value_for_enums() {
279258
.add_source(config::Environment::with_prefix("APPS").separator("_"))
280259
.build()
281260
.unwrap();
282-
let val: EnumSettings = cfg.try_deserialize().unwrap();
283261

284-
assert_eq!(
285-
val,
286-
EnumSettings::Bar("I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_owned())
262+
let param = cfg.try_deserialize::<EnumSettings>();
263+
assert!(param.is_err());
264+
assert_data_eq!(
265+
param.unwrap_err().to_string(),
266+
str!["enum EnumSettings does not have variant constructor bar"]
287267
);
288268
}
289269

@@ -309,11 +289,11 @@ fn test_override_lowercase_value_for_enums() {
309289
.build()
310290
.unwrap();
311291

312-
let param: EnumSettings = cfg.try_deserialize().unwrap();
313-
314-
assert_eq!(
315-
param,
316-
EnumSettings::Bar("I have been overridden_with_lower_case".to_owned())
292+
let param = cfg.try_deserialize::<EnumSettings>();
293+
assert!(param.is_err());
294+
assert_data_eq!(
295+
param.unwrap_err().to_string(),
296+
str!["enum EnumSettings does not have variant constructor bar"]
317297
);
318298
}
319299

0 commit comments

Comments
 (0)