Skip to content

Commit 33b8cf0

Browse files
committed
WIP Case sensitivity support
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
1 parent 5ae097d commit 33b8cf0

File tree

3 files changed

+46
-5
lines changed

3 files changed

+46
-5
lines changed

src/config.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,24 +39,46 @@ impl Default for ConfigKind {
3939
/// A prioritized configuration repository. It maintains a set of
4040
/// configuration sources, fetches values to populate those, and provides
4141
/// them according to the source's priority.
42+
///
43+
/// By default, keys and enum variants are deserialized case sensitive, so "FOO" != "foo"
4244
#[derive(Clone, Debug)]
4345
pub struct Config {
4446
kind: ConfigKind,
4547

4648
/// Root of the cached configuration.
4749
pub cache: Value,
50+
51+
/// Flag whether keys should be deserialized case-sensitive
52+
pub(crate) keys_case_sensitive: bool,
53+
54+
/// Flag whether enum variants should be deserialized case-sensitive
55+
pub(crate) enum_variants_case_sensitive: bool,
4856
}
4957

5058
impl Default for Config {
5159
fn default() -> Self {
5260
Config {
5361
kind: ConfigKind::default(),
5462
cache: Value::new(None, Table::new()),
63+
keys_case_sensitive: true,
64+
enum_variants_case_sensitive: true,
5565
}
5666
}
5767
}
5868

5969
impl Config {
70+
pub fn with_keys_case_sensitive(mut self, b: bool) -> Self {
71+
self.keys_case_sensitive = b;
72+
self.cache.keys_case_sensitive = b;
73+
self
74+
}
75+
76+
pub fn with_enum_variants_case_sensitive(mut self, b: bool) -> Self {
77+
self.enum_variants_case_sensitive = b;
78+
self.cache.enum_variants_case_sensitive = b;
79+
self
80+
}
81+
6082
/// Merge in a configuration property source.
6183
pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
6284
where

src/de.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<'de> de::Deserializer<'de> for Value {
2121
ValueKind::Float(f) => visitor.visit_f64(f),
2222
ValueKind::String(s) => visitor.visit_string(s),
2323
ValueKind::Array(values) => visitor.visit_seq(SeqAccess::new(values)),
24-
ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map)),
24+
ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map, self.keys_case_sensitive, self.enum_variants_case_sensitive)),
2525
}
2626
}
2727

@@ -126,6 +126,7 @@ impl<'de> de::Deserializer<'de> for Value {
126126
V: de::Visitor<'de>,
127127
{
128128
visitor.visit_enum(EnumAccess {
129+
variants_case_sensitive: self.enum_variants_case_sensitive,
129130
value: self,
130131
name,
131132
variants,
@@ -200,12 +201,16 @@ impl<'de> de::SeqAccess<'de> for SeqAccess {
200201

201202
struct MapAccess {
202203
elements: VecDeque<(String, Value)>,
204+
keys_case_sensitive: bool,
205+
enum_variants_case_sensitive: bool,
203206
}
204207

205208
impl MapAccess {
206-
fn new(table: HashMap<String, Value>) -> Self {
209+
fn new(table: HashMap<String, Value>, keys_case_sensitive: bool, enum_variants_case_sensitive: bool) -> Self {
207210
MapAccess {
208211
elements: table.into_iter().collect(),
212+
keys_case_sensitive,
213+
enum_variants_case_sensitive,
209214
}
210215
}
211216
}
@@ -218,7 +223,9 @@ impl<'de> de::MapAccess<'de> for MapAccess {
218223
K: de::DeserializeSeed<'de>,
219224
{
220225
if let Some(&(ref key_s, _)) = self.elements.front() {
221-
let key_de = Value::new(None, key_s as &str);
226+
let mut key_de = Value::new(None, key_s as &str);
227+
key_de.keys_case_sensitive = self.keys_case_sensitive;
228+
key_de.enum_variants_case_sensitive = self.enum_variants_case_sensitive;
222229
let key = de::DeserializeSeed::deserialize(seed, key_de)?;
223230

224231
Ok(Some(key))
@@ -240,13 +247,14 @@ struct EnumAccess {
240247
value: Value,
241248
name: &'static str,
242249
variants: &'static [&'static str],
250+
variants_case_sensitive: bool,
243251
}
244252

245253
impl EnumAccess {
246254
fn variant_deserializer(&self, name: &str) -> Result<StrDeserializer> {
247255
self.variants
248256
.iter()
249-
.find(|&&s| s == name)
257+
.find(|&&s| s == name || (!self.variants_case_sensitive && s.eq_ignore_ascii_case(name)))
250258
.map(|&s| StrDeserializer(s))
251259
.ok_or_else(|| self.no_constructor_error(name))
252260
}
@@ -353,7 +361,7 @@ impl<'de> de::Deserializer<'de> for Config {
353361
ValueKind::Float(f) => visitor.visit_f64(f),
354362
ValueKind::String(s) => visitor.visit_string(s),
355363
ValueKind::Array(values) => visitor.visit_seq(SeqAccess::new(values)),
356-
ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map)),
364+
ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map, self.keys_case_sensitive, self.enum_variants_case_sensitive)),
357365
}
358366
}
359367

@@ -454,6 +462,7 @@ impl<'de> de::Deserializer<'de> for Config {
454462
value: self.cache,
455463
name,
456464
variants,
465+
variants_case_sensitive: self.enum_variants_case_sensitive,
457466
})
458467
}
459468

src/value.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ pub struct Value {
136136

137137
/// Underlying kind of the configuration value.
138138
pub kind: ValueKind,
139+
140+
/// Flag whether keys should be deserialized case-sensitive
141+
pub(crate) keys_case_sensitive: bool,
142+
143+
/// Flag whether enum variants should be deserialized case-sensitive
144+
pub(crate) enum_variants_case_sensitive: bool,
139145
}
140146

141147
impl Value {
@@ -147,6 +153,8 @@ impl Value {
147153
Value {
148154
origin: origin.cloned(),
149155
kind: kind.into(),
156+
keys_case_sensitive: true,
157+
enum_variants_case_sensitive: true,
150158
}
151159
}
152160

@@ -533,6 +541,8 @@ where
533541
Value {
534542
origin: None,
535543
kind: value.into(),
544+
keys_case_sensitive: true,
545+
enum_variants_case_sensitive: true,
536546
}
537547
}
538548
}

0 commit comments

Comments
 (0)