use std::fmt;
#[derive(Debug, Clone)]
pub struct ConfigKey {
env: String,
parts: Vec<(String, usize)>,
}
impl ConfigKey {
pub fn new() -> ConfigKey {
ConfigKey {
env: "CARGO".to_string(),
parts: Vec::new(),
}
}
pub fn from_str(key: &str) -> ConfigKey {
let mut cfg = ConfigKey::new();
for part in key.split('.') {
cfg.push(part);
}
cfg
}
pub fn push(&mut self, name: &str) {
let env = name.replace("-", "_").to_uppercase();
self._push(&env, name);
}
pub fn push_sensitive(&mut self, name: &str) {
self._push(name, name);
}
fn _push(&mut self, env: &str, config: &str) {
self.parts.push((config.to_string(), self.env.len()));
self.env.push_str("_");
self.env.push_str(env);
}
pub fn pop(&mut self) {
let (_part, env) = self.parts.pop().unwrap();
self.env.truncate(env);
}
pub fn as_env_key(&self) -> &str {
&self.env
}
pub(super) fn parts(&self) -> impl Iterator<Item = &str> {
self.parts.iter().map(|p| p.0.as_ref())
}
}
impl fmt::Display for ConfigKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let parts: Vec<&str> = self.parts().collect();
parts.join(".").fmt(f)
}
}