use std::ffi::OsString;
use crate::config::EnvKey;
use crate::error::HomeVariable;
pub trait ParentEnv: Fn(&str) -> Option<OsString> {}
impl<F: Fn(&str) -> Option<OsString>> ParentEnv for F {}
#[must_use]
pub fn process_env(key: &str) -> Option<OsString> {
std::env::var_os(key)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ManagedEnvVar {
Path,
Home,
UserProfile,
NoDefaultCurrentDirectoryInExePath,
}
impl ManagedEnvVar {
#[cfg(test)]
pub const ALL: [Self; 4] = [
Self::Path,
Self::Home,
Self::UserProfile,
Self::NoDefaultCurrentDirectoryInExePath,
];
#[must_use]
pub const fn key(self) -> EnvKey {
EnvKey::from_static(self.name())
}
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Path => "PATH",
Self::Home => HomeVariable::Home.name(),
Self::UserProfile => HomeVariable::UserProfile.name(),
Self::NoDefaultCurrentDirectoryInExePath => "NoDefaultCurrentDirectoryInExePath",
}
}
}
impl From<HomeVariable> for ManagedEnvVar {
fn from(variable: HomeVariable) -> Self {
match variable {
HomeVariable::Home => Self::Home,
HomeVariable::UserProfile => Self::UserProfile,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn managed_names_match_the_home_variables() {
for variable in HomeVariable::ALL {
assert_eq!(ManagedEnvVar::from(variable).name(), variable.name());
}
}
#[test]
fn managed_names_are_distinct() {
let mut names: Vec<_> = ManagedEnvVar::ALL.map(ManagedEnvVar::name).into();
names.sort_unstable();
names.dedup();
assert_eq!(names.len(), ManagedEnvVar::ALL.len());
}
#[test]
fn closures_are_parent_envs() {
fn read(env: impl ParentEnv) -> Option<OsString> {
env("KEY")
}
assert_eq!(read(|_| Some("v".into())), Some(OsString::from("v")));
assert_eq!(read(|_| None), None);
}
}