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
//! # `menv`
//! This crate provides [a macro](require_envs) for asserting the presence of a list of environment
//! variables and accessing them as types which implement [`FromStr`](std::str::FromStr).
/// Generate the following:
/// - A function which asserts the presence and well-formedness of a list of env vars
/// - A function which returns a `bool` representing whether any of the required vars are set
/// - A function which returns a `String` representing the collected help messages for the list of vars
/// - A list of functions, one for each environment variable required
///
/// # Example
/// Here we fill an `env` module with required environment variables,
/// print help and exit if none of them are set, runs the asserts for them
/// if some are set, and proceeds.
/// Other parts of this program are now free, since the asserts were run at the start of main,
/// to access `env::server_port()` and `env::db_path()` as if they are infallible.
/// ```
/// mod env {
/// use menv::require_envs;
/// require_envs! {
/// (assert_env_vars, any_set, gen_help);
///
/// server_port, "FERRISCRAFT_USERS_PORT", u16,
/// "FERRISCRAFT_USERS_PORT should be set to the desired server port";
///
/// db_path, "FERRISCRAFT_USERS_DB", String,
/// "FERRISCRAFT_USERS_DB should be set to the path to the users database";
/// }
/// }
/// fn main() {
/// if env::any_set() {
/// env::assert_env_vars();
/// } else {
/// println!("# Environment Variables Help\n{}", env::gen_help());
/// return
/// }
/// }
/// ```
#[macro_export]
macro_rules! require_envs {
(($assert_name:ident, $any_set_name:ident, $help_name:ident); $($fname:ident, $ename:literal, $ty:ty, $etext:literal);* $(;)?) => {
pub fn $assert_name () {
// TODO: comment out this body to check if vars are unused
$(
let _ = $fname();
)*
}
pub fn $any_set_name() -> bool {
[$(::std::env::var($ename)),*].iter().any(|x| x.is_ok())
}
pub fn $help_name() -> String {
String::new() $(+ $etext + "\n")*
}
$(
pub fn $fname() -> $ty {
::std::str::FromStr::from_str(&::std::env::var($ename).expect($etext)).expect($etext)
}
)*
}
}