use std::collections::BTreeMap;
use std::sync::Arc;
pub type AmbientLookup = Arc<dyn Fn(&str) -> Option<String> + Send + Sync>;
pub struct LayeredEnv {
doc: BTreeMap<String, String>,
harness_provisioned: BTreeMap<String, String>,
passthrough: Vec<String>,
ambient: AmbientLookup,
}
impl LayeredEnv {
pub fn new(
doc: BTreeMap<String, String>,
harness_provisioned: BTreeMap<String, String>,
passthrough: Vec<String>,
ambient: AmbientLookup,
) -> Self {
Self {
doc,
harness_provisioned,
passthrough,
ambient,
}
}
pub fn lookup(&self, key: &str) -> Option<String> {
if let Some(value) = self.harness_provisioned.get(key) {
return Some(value.clone());
}
if let Some(value) = self.doc.get(key) {
return Some(value.clone());
}
if self.passthrough.iter().any(|allowed| allowed == key) {
return (self.ambient)(key);
}
None
}
pub fn with_harness_var(&self, key: &str, value: String) -> LayeredEnv {
let mut harness_provisioned = self.harness_provisioned.clone();
harness_provisioned.insert(key.to_string(), value);
LayeredEnv {
doc: self.doc.clone(),
harness_provisioned,
passthrough: self.passthrough.clone(),
ambient: Arc::clone(&self.ambient),
}
}
}
pub fn ambient_std() -> AmbientLookup {
Arc::new(|key| std::env::var(key).ok())
}