use std::ffi::OsStr;
use std::fmt::Debug;
#[derive(Clone, Debug)]
pub struct Cache {
#[cfg(feature = "envvars")]
pub envvars: (),
#[cfg(feature = "envfiles")]
pub envfiles: (),
#[cfg(feature = "envdot")]
pub envdot: Vec<crate::envdot::DotEnv>,
}
impl Default for Cache {
fn default() -> Self {
let mut this = Self::new();
this.envdot_register("./.env.local");
this.envdot_register("./.env");
this
}
}
impl Cache {
pub fn new() -> Self {
Self {
envvars: Default::default(),
envfiles: Default::default(),
envdot: Default::default(),
}
}
#[cfg(feature = "envdot")]
pub fn envdot_register<Path>(&mut self, path: Path)
where Path: AsRef<std::path::Path> + Debug
{
let dotenv = crate::envdot::parse_dotenv(path);
if let Some(dotenv) = dotenv {
self.envdot.push(dotenv);
}
}
pub fn get(&self, key: &OsStr) -> Option<String>
{
let mut value = None;
if value.is_none() { value = self.get_from_envfiles(key); }
if value.is_none() { value = self.get_from_envvars(key); }
if value.is_none() { value = self.get_from_envdot(key); }
value
}
#[cfg(feature = "envfiles")]
pub fn get_from_envfiles(&self, key: &OsStr) -> Option<String> {
crate::envfiles::get(key)
}
#[cfg(not(feature = "envfiles"))]
pub fn get_from_envfiles(&self, _key: &OsStr) -> Option<String> {
None
}
#[cfg(feature = "envvars")]
pub fn get_from_envvars(&self, key: &OsStr) -> Option<String> {
crate::envvars::get(key)
}
#[cfg(not(feature = "envvars"))]
pub fn get_from_envvars(&self, _key: &OsStr) -> Option<String> {
None
}
#[cfg(feature = "envdot")]
pub fn get_from_envdot(&self, key: &OsStr) -> Option<String> {
for dotenv in self.envdot.iter() {
let value = crate::envdot::get(dotenv, key);
if value.is_some() {
return value
}
}
None
}
#[cfg(not(feature = "envdot"))]
pub fn get_from_envdot(&self, _key: &OsStr) -> Option<String> {
None
}
}
#[cfg(test)]
mod tests {
use crate::testing::tempfile_fixture;
use super::*;
#[cfg(feature = "envdot")]
#[test]
fn envdot_register() {
let file = tempfile_fixture(
r#"
GARAS=garas
export AUTO= auto
BUS = bus
"#
);
let mut cache = Cache::new();
cache.envdot_register(file.as_os_str());
assert_eq!(cache.envdot.len(), 1);
}
#[cfg(feature = "envvars")]
#[test]
fn get_envvars() {
std::env::set_var("GARAS", "garas");
std::env::remove_var("GARAS_FILE");
let cache = Cache::new();
assert_eq!(cache.get("GARAS".as_ref()), Some("garas".to_string()));
}
#[cfg(feature = "envfiles")]
#[test]
fn get_envfiles() {
let file = tempfile_fixture("garas");
std::env::remove_var("GARAS");
std::env::set_var("GARAS_FILE", file.as_os_str());
let cache = Cache::new();
assert_eq!(cache.get("GARAS".as_ref()), Some("garas".to_string()));
}
#[cfg(feature = "envdot")]
#[test]
fn get_envdot() {
std::env::remove_var("POTATO");
std::env::remove_var("POTATO_FILE");
let file = tempfile_fixture(
r#"POTATO=tomato"#
);
let mut cache = Cache::default();
cache.envdot_register(file.as_os_str());
assert_eq!(cache.get("POTATO".as_ref()), Some("tomato".to_string()));
}
#[test]
#[cfg(all(feature = "envdot", feature = "envfiles", feature = "envvars"))]
fn priority() {
let mut cache = Cache::default();
let envfiles_file = tempfile_fixture("envfiles");
let envdot_file = tempfile_fixture(
r#"
export ENVFILES=envdot
export ENVVARS=envdot
export ENVDOT=envdot
"#
);
std::env::set_var("ENVFILES_FILE", envfiles_file.as_os_str());
std::env::remove_var("ENVVARS_FILE");
std::env::remove_var("ENVDOT_FILE");
std::env::remove_var("NONE_FILE");
std::env::set_var("ENVFILES", "envvars");
std::env::set_var("ENVVARS", "envvars");
std::env::remove_var("ENVDOT");
std::env::remove_var("NONE");
cache.envdot_register(envdot_file.as_os_str());
assert_eq!(cache.get("ENVFILES".as_ref()), Some("envfiles".to_string()));
assert_eq!(cache.get("ENVVARS".as_ref()), Some("envvars".to_string()));
assert_eq!(cache.get("ENVDOT".as_ref()), Some("envdot".to_string()));
assert_eq!(cache.get("NONE".as_ref()), None);
}
}