use std::collections::HashMap;
use crate::{Result, RhoodError};
pub trait Env {
fn get(&self, key: &str) -> Option<String>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct SystemEnv;
impl Env for SystemEnv {
fn get(&self, key: &str) -> Option<String> {
std::env::var(key).ok()
}
}
#[derive(Debug, Default, Clone)]
pub struct MapEnv {
vars: HashMap<String, String>,
}
impl MapEnv {
pub fn new() -> Self {
Self::default()
}
pub fn with<K, V>(mut self, key: K, value: V) -> Self
where
K: Into<String>,
V: Into<String>,
{
self.vars.insert(key.into(), value.into());
self
}
}
impl Env for MapEnv {
fn get(&self, key: &str) -> Option<String> {
self.vars.get(key).cloned()
}
}
pub fn env_non_empty(env: &impl Env, key: &str) -> Option<String> {
env.get(key).filter(|value| !value.is_empty())
}
pub fn env_parsed<T>(env: &impl Env, key: &str) -> Result<Option<T>>
where
T: std::str::FromStr,
T::Err: std::fmt::Display,
{
let Some(value) = env_non_empty(env, key) else {
return Ok(None);
};
value.parse().map(Some).map_err(|error| {
RhoodError::InvalidParameter(format!(
"environment variable {key} has invalid value {value:?}: {error}"
))
})
}