pub(crate) trait Environment {
fn read_os(&self, key: &str) -> Option<std::ffi::OsString>;
fn read(&self, key: &str) -> Result<String, std::env::VarError> {
self.read_os(key).map_or_else(
|| Err(std::env::VarError::NotPresent),
|s| s.into_string().map_err(std::env::VarError::NotUnicode),
)
}
fn is_defined(&self, key: &str) -> bool {
self.read_os(key).is_some()
}
fn is_non_empty(&self, key: &str) -> bool {
self.read_os(key).is_some_and(|v| !v.is_empty())
}
fn has_value(&self, key: &str, expected_value: &str) -> bool {
self.read_os(key).is_some_and(|v| v == expected_value)
}
}
#[derive(Debug, Default)]
pub(crate) struct Env();
impl Environment for Env {
fn read_os(&self, key: &str) -> Option<std::ffi::OsString> {
std::env::var_os(key)
}
}
#[cfg(test)]
mod test {
use super::Environment;
use std::collections::HashMap;
pub(crate) struct FakeEnv {
bindings: HashMap<String, String>,
}
impl FakeEnv {
pub(crate) fn new() -> FakeEnv {
FakeEnv {
bindings: HashMap::new(),
}
}
pub(crate) fn set(&mut self, key: impl AsRef<str>, value: impl AsRef<str>) -> &mut Self {
self.bindings
.insert(key.as_ref().to_string(), value.as_ref().to_string());
self
}
}
impl Environment for FakeEnv {
fn read_os(&self, key: &str) -> Option<std::ffi::OsString> {
self.bindings.get(key).map(|v| v.into())
}
}
}
#[cfg(test)]
pub(crate) use test::FakeEnv;