#![cfg_attr(docsrs, feature(doc_cfg))]
use std::{path::PathBuf, sync::atomic::AtomicBool};
pub use vne_macros::{build, vne};
static HAS_VALIDATED: AtomicBool = AtomicBool::new(false);
pub struct Environment {
envs: &'static [&'static str],
}
impl Environment {
pub fn load(self, path: impl Into<PathBuf>) -> Self {
let path = path.into();
if path.join(".env").exists() {
let raw = std::fs::read_to_string(path.join(".env"))
.expect("vne error: failed to read environment file");
let envs = raw
.lines()
.map(|v| v.trim())
.filter(|v| !v.is_empty())
.filter(|v| !v.starts_with('#'))
.map(|v| v.splitn(2, "="))
.map(|mut v| (v.next().unwrap(), v.next().unwrap().trim_matches('"')));
for (key, value) in envs {
if std::env::var(key).is_err() {
std::env::set_var(key, value);
}
}
} else {
panic!("vne error: failed to find .env file")
}
self
}
pub fn validate(&self) -> Result<(), String> {
for env in self.envs {
if std::env::var(env).is_err() {
return Err(format!("vne error: missing environment variable {env:?}"));
}
}
HAS_VALIDATED.store(true, std::sync::atomic::Ordering::SeqCst);
Ok(())
}
}
#[doc(hidden)]
pub mod internal {
use super::*;
pub const fn construct_env(envs: &'static [&'static str]) -> Environment {
Environment { envs }
}
pub fn from_env(key: &'static str) -> String {
if !HAS_VALIDATED.load(std::sync::atomic::Ordering::SeqCst) {
panic!("vne error: attempted to access environment variable before validation was run");
}
std::env::var(key).expect("vne error: unreachable failed to get env")
}
}