diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2021-03-28 18:13:08 +0200 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2021-07-10 15:37:45 +0200 |
commit | dca0874d1dc89c341d1f17fbabca3ff6d17e48d5 (patch) | |
tree | b99948eca4b966f079c61e2ee550c794aafb5834 | |
parent | 8e8a9d9dea801dbc68324276f486deb512df08e3 (diff) |
WIP Case sensitivity supportcase-sensitivity-support
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r-- | src/config.rs | 29 | ||||
-rw-r--r-- | src/de.rs | 19 | ||||
-rw-r--r-- | src/value.rs | 10 |
3 files changed, 46 insertions, 12 deletions
diff --git a/src/config.rs b/src/config.rs index b9c64b4..fa95063 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,6 +14,8 @@ use crate::value::{Table, Value}; /// A prioritized configuration repository. It maintains a set of /// configuration sources, fetches values to populate those, and provides /// them according to the source's priority. +/// +/// By default, keys and enum variants are deserialized case sensitive, so "FOO" != "foo" #[derive(Clone, Debug)] pub struct Config { defaults: HashMap<path::Expression, Value>, @@ -22,6 +24,12 @@ pub struct Config { /// Root of the cached configuration. pub cache: Value, + + /// Flag whether keys should be deserialized case-sensitive + pub(crate) keys_case_sensitive: bool, + + /// Flag whether enum variants should be deserialized case-sensitive + pub(crate) enum_variants_case_sensitive: bool, } impl Default for Config { @@ -31,23 +39,30 @@ impl Default for Config { overrides: Default::default(), sources: Default::default(), cache: Value::new(None, Table::new()), + keys_case_sensitive: true, + enum_variants_case_sensitive: true, } } } impl Config { - pub(crate) fn new(value: Value) -> Self { - Config { - cache: value, - ..Default::default() - } - } - /// Creates new [`ConfigBuilder`] instance pub fn builder() -> ConfigBuilder<DefaultState> { ConfigBuilder::<DefaultState>::default() } + pub fn with_keys_case_sensitive(mut self, b: bool) -> Self { + self.keys_case_sensitive = b; + self.cache.keys_case_sensitive = b; + self + } + + pub fn with_enum_variants_case_sensitive(mut self, b: bool) -> Self { + self.enum_variants_case_sensitive = b; + self.cache.enum_variants_case_sensitive = b; + self + } + /// Merge in a configuration property source. #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")] pub fn merge<T>(&mut self, source: T) -> Result<&mut Config> @@ -23,7 +23,7 @@ impl<'de> de::Deserializer<'de> for Value { ValueKind::Float(f) => visitor.visit_f64(f), ValueKind::String(s) => visitor.visit_string(s), ValueKind::Array(values) => visitor.visit_seq(SeqAccess::new(values)), - ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map)), + ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map, self.keys_case_sensitive, self.enum_variants_case_sensitive)), } } @@ -128,6 +128,7 @@ impl<'de> de::Deserializer<'de> for Value { V: de::Visitor<'de>, { visitor.visit_enum(EnumAccess { + variants_case_sensitive: self.enum_variants_case_sensitive, value: self, name, variants, @@ -196,12 +197,16 @@ impl<'de> de::SeqAccess<'de> for SeqAccess { struct MapAccess { elements: VecDeque<(String, Value)>, + keys_case_sensitive: bool, + enum_variants_case_sensitive: bool, } impl MapAccess { - fn new(table: HashMap<String, Value>) -> Self { + fn new(table: HashMap<String, Value>, keys_case_sensitive: bool, enum_variants_case_sensitive: bool) -> Self { MapAccess { elements: table.into_iter().collect(), + keys_case_sensitive, + enum_variants_case_sensitive, } } } @@ -214,7 +219,9 @@ impl<'de> de::MapAccess<'de> for MapAccess { K: de::DeserializeSeed<'de>, { if let Some(&(ref key_s, _)) = self.elements.front() { - let key_de = Value::new(None, key_s as &str); + let mut key_de = Value::new(None, key_s as &str); + key_de.keys_case_sensitive = self.keys_case_sensitive; + key_de.enum_variants_case_sensitive = self.enum_variants_case_sensitive; let key = de::DeserializeSeed::deserialize(seed, key_de)?; Ok(Some(key)) @@ -236,13 +243,14 @@ struct EnumAccess { value: Value, name: &'static str, variants: &'static [&'static str], + variants_case_sensitive: bool, } impl EnumAccess { fn variant_deserializer(&self, name: &str) -> Result<StrDeserializer> { self.variants .iter() - .find(|&&s| s == name) + .find(|&&s| s == name || (!self.variants_case_sensitive && s.eq_ignore_ascii_case(name))) .map(|&s| StrDeserializer(s)) .ok_or_else(|| self.no_constructor_error(name)) } @@ -349,7 +357,7 @@ impl<'de> de::Deserializer<'de> for Config { ValueKind::Float(f) => visitor.visit_f64(f), ValueKind::String(s) => visitor.visit_string(s), ValueKind::Array(values) => visitor.visit_seq(SeqAccess::new(values)), - ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map)), + ValueKind::Table(map) => visitor.visit_map(MapAccess::new(map, self.keys_case_sensitive, self.enum_variants_case_sensitive)), } } @@ -450,6 +458,7 @@ impl<'de> de::Deserializer<'de> for Config { value: self.cache, name, variants, + variants_case_sensitive: self.enum_variants_case_sensitive, }) } diff --git a/src/value.rs b/src/value.rs index 8db5fcc..69cd07a 100644 --- a/src/value.rs +++ b/src/value.rs @@ -136,6 +136,12 @@ pub struct Value { /// Underlying kind of the configuration value. pub kind: ValueKind, + + /// Flag whether keys should be deserialized case-sensitive + pub(crate) keys_case_sensitive: bool, + + /// Flag whether enum variants should be deserialized case-sensitive + pub(crate) enum_variants_case_sensitive: bool, } impl Value { @@ -147,6 +153,8 @@ impl Value { Value { origin: origin.cloned(), kind: kind.into(), + keys_case_sensitive: true, + enum_variants_case_sensitive: true, } } @@ -533,6 +541,8 @@ where Value { origin: None, kind: value.into(), + keys_case_sensitive: true, + enum_variants_case_sensitive: true, } } } |