use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ImmutableEnvironmentContext {
pub(crate) base_working_dir: Arc<PathBuf>,
pub(crate) env_vars: Arc<HashMap<String, String>>,
pub(crate) secret_keys: Arc<Vec<String>>,
pub(crate) profile: Option<Arc<str>>,
}
impl ImmutableEnvironmentContext {
pub fn new(base_working_dir: PathBuf) -> Self {
Self {
base_working_dir: Arc::new(base_working_dir),
env_vars: Arc::new(HashMap::new()),
secret_keys: Arc::new(Vec::new()),
profile: None,
}
}
pub fn working_dir(&self) -> &Path {
&self.base_working_dir
}
pub fn env_vars(&self) -> &HashMap<String, String> {
&self.env_vars
}
pub fn is_secret(&self, key: &str) -> bool {
self.secret_keys.contains(&key.to_string())
}
pub fn profile(&self) -> Option<&str> {
self.profile.as_deref()
}
pub fn secret_keys(&self) -> &[String] {
&self.secret_keys
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_context() {
let context = ImmutableEnvironmentContext::new(PathBuf::from("/test"));
assert_eq!(context.working_dir(), Path::new("/test"));
assert!(context.env_vars().is_empty());
assert!(context.secret_keys().is_empty());
assert!(context.profile().is_none());
}
#[test]
fn test_context_is_immutable() {
let context = ImmutableEnvironmentContext::new(PathBuf::from("/test"));
let _dir = context.working_dir();
let _env = context.env_vars();
let _secrets = context.secret_keys();
}
#[test]
fn test_context_clone_is_cheap() {
let mut vars = HashMap::new();
vars.insert("KEY".to_string(), "value".to_string());
let context = ImmutableEnvironmentContext {
base_working_dir: Arc::new(PathBuf::from("/test")),
env_vars: Arc::new(vars),
secret_keys: Arc::new(vec!["SECRET".to_string()]),
profile: Some(Arc::from("prod")),
};
let cloned = context.clone();
assert!(Arc::ptr_eq(
&context.base_working_dir,
&cloned.base_working_dir
));
assert!(Arc::ptr_eq(&context.env_vars, &cloned.env_vars));
assert!(Arc::ptr_eq(&context.secret_keys, &cloned.secret_keys));
}
#[test]
fn test_is_secret() {
let context = ImmutableEnvironmentContext {
base_working_dir: Arc::new(PathBuf::from("/test")),
env_vars: Arc::new(HashMap::new()),
secret_keys: Arc::new(vec!["API_KEY".to_string(), "TOKEN".to_string()]),
profile: None,
};
assert!(context.is_secret("API_KEY"));
assert!(context.is_secret("TOKEN"));
assert!(!context.is_secret("NORMAL_VAR"));
}
#[test]
fn test_profile() {
let context = ImmutableEnvironmentContext {
base_working_dir: Arc::new(PathBuf::from("/test")),
env_vars: Arc::new(HashMap::new()),
secret_keys: Arc::new(Vec::new()),
profile: Some(Arc::from("production")),
};
assert_eq!(context.profile(), Some("production"));
}
}