#![forbid(unsafe_code)]
mod parse;
pub use crate::parse::parse;
pub use crate::parse::Entry;
pub use crate::parse::Parsed;
use std::path::Path;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Loaded {
pub found: bool,
pub applied: Vec<String>,
pub overridden: Vec<String>,
pub repeated: Vec<String>,
pub skipped: Vec<usize>,
}
pub fn load(path: &Path) -> Loaded {
let content = match std::fs::read_to_string(path) {
Ok(content) => content,
Err(_) => return Loaded::default(),
};
let parsed = parse(&content);
let mut loaded = Loaded {
found: true,
skipped: parsed.skipped,
..Loaded::default()
};
for entry in parsed.entries {
match fate_of(entry.key, &loaded.applied, &loaded.overridden) {
Fate::Repeated => loaded.repeated.push(entry.key.to_owned()),
Fate::Overridden => loaded.overridden.push(entry.key.to_owned()),
Fate::Applied => {
std::env::set_var(entry.key, entry.value);
loaded.applied.push(entry.key.to_owned());
}
}
}
loaded
}
enum Fate {
Repeated,
Overridden,
Applied,
}
fn fate_of(key: &str, applied: &[String], overridden: &[String]) -> Fate {
if contains_name(applied, key) || contains_name(overridden, key) {
return Fate::Repeated;
}
if std::env::var_os(key).is_some() {
return Fate::Overridden;
}
Fate::Applied
}
fn contains_name(names: &[String], key: &str) -> bool {
names.iter().any(|name| name == key)
}