1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
use std::{
env::{self, VarError},
str::FromStr,
};
use anyhow::{anyhow, Context, Error, Result};
/// Load and parse the value of an environment variable.
///
/// # Arguments
///
/// * `name` - name of the environment variable to load.
pub fn mandatory<T>(name: &str) -> Result<T>
where
T: FromStr,
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
{
var(name, None)
}
/// Load and parse the value of an environment variable.
///
/// # Arguments
///
/// * `name` - name of the environment variable to load.
///
/// * `default` - default value to be returned if the environment variable is
/// not set.
pub fn optional<T>(name: &str, default: T) -> Result<T>
where
T: FromStr,
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
{
var(name, Some(default))
}
/// Load and parse the value of an environment variable.
///
/// # Arguments
///
/// * `name` - name of the environment variable to load.
///
/// * `default` - default value to use if the environment variable is not set.
/// An error is returned if both the env variable is not set and the default
/// value is None.
fn var<T>(name: &str, default: Option<T>) -> Result<T>
where
T: FromStr,
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
{
match env::var(name) {
Ok(value) => T::from_str(value.as_str())
.with_context(|| format!("Failed to parse environment variable \"{name}\"")),
Err(VarError::NotPresent) => match default {
Some(value) => Ok(value),
None => Err(anyhow!(format!(
"Mandatory environment variable \"{name}\" is not set."
))),
},
Err(error) => {
Err(Error::new(error)
.context(format!("Failed to load environment variable \"{name}\"")))
}
}
}