lexe_common/dotenv.rs
1use std::env;
2
3/// A version of [`dotenvy::dotenv`] which only loads whitelisted keys.
4///
5/// # Safety
6///
7/// This fn calls [`std::env::set_var`] under-the-hood, which is not
8/// threadsafe on some platforms (ex: glibc Linux). The caller must ensure that
9/// this fn is called very early in the program lifetime, before any threads are
10/// spawned.
11pub unsafe fn dotenv_filtered(
12 filter_keys: &[&str],
13) -> Result<(), dotenvy::Error> {
14 // `dotenv_iter` finds an .env file in the current directory (or parents),
15 // then returns an iterator over it without loading the variables within.
16 for try_kv in dotenvy::dotenv_iter()? {
17 let (key, value) = try_kv?;
18 if filter_keys.contains(&key.as_str()) {
19 // Like dotenvy::dotenv(), do not override existing keys.
20 if env::var(&key).is_err() {
21 // See SAFETY
22 unsafe {
23 env::set_var(&key, value);
24 }
25 }
26 }
27 }
28
29 Ok(())
30}
31
32/// Fetches the given key from env or `.env`, but without loading any of the
33/// keys in `.env` into our env (including the requested key).
34/// In other words, it is a "pure" version of [`dotenvy::var`].
35pub fn var_pure(given_key: &str) -> Result<String, dotenvy::Error> {
36 // Early return if the key already existed in env.
37 if let Ok(value) = env::var(given_key) {
38 return Ok(value);
39 }
40
41 // Look for the key in .env. We do not set the key in env if it was found.
42 for try_kv in dotenvy::dotenv_iter()? {
43 let (key, value) = try_kv?;
44 if key == given_key {
45 return Ok(value);
46 }
47 }
48
49 Err(dotenvy::Error::EnvVar(env::VarError::NotPresent))
50}