use std::ffi::{OsStr, OsString};
use std::sync::{Mutex, MutexGuard, OnceLock};
pub fn env_lock() -> &'static Mutex<()> {
static LOCK: OnceLock<Mutex<()>> = OnceLock::new();
LOCK.get_or_init(|| Mutex::new(()))
}
pub fn lock_env() -> MutexGuard<'static, ()> {
env_lock()
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner())
}
pub struct ScopedEnvVar {
key: &'static str,
original: Option<OsString>,
}
impl ScopedEnvVar {
pub fn set(key: &'static str, value: impl AsRef<OsStr>) -> Self {
let original = std::env::var_os(key);
unsafe {
std::env::set_var(key, value);
}
Self { key, original }
}
pub fn unset(key: &'static str) -> Self {
let original = std::env::var_os(key);
unsafe {
std::env::remove_var(key);
}
Self { key, original }
}
}
impl Drop for ScopedEnvVar {
fn drop(&mut self) {
match &self.original {
Some(value) => unsafe {
std::env::set_var(self.key, value);
},
None => unsafe {
std::env::remove_var(self.key);
},
}
}
}