arcs_env_rs/
lib.rs

1use std::fmt::{Display, Debug};
2
3#[doc(hidden)]
4pub use paste::paste;
5#[doc(hidden)]
6pub use lazy_static::lazy_static;
7
8#[macro_export]
9macro_rules! env_var_opt {
10    ($env_name:ident  $(-> $short_name:ident)?) => {
11        env_var_opt!(impl $env_name, $($short_name)? $env_name);
12    };
13
14    (impl $env_name:ident, $var_name:ident $($extra:ident)?) => {
15        $crate::paste! {
16            $crate::lazy_static! {
17                pub static ref $var_name: Option<String> = std::env::var(stringify!($env_name)).ok();
18            }
19            pub fn [<$var_name:lower>]() -> Option<&'static str> {
20                $var_name.as_ref().map(|s| s.as_str())
21            }
22        }
23    }
24}
25
26#[macro_export]
27macro_rules! env_var_opt_default {
28    ($env_name:ident (default $default_env_name:ident) $(-> $short_name:ident)?) => {
29        env_var_opt_default!(impl $env_name, $default_env_name, $($short_name)? $env_name);
30    };
31
32    (impl $env_name:ident, $default_env_name:ident, $var_name:ident $($extra:ident)?) => {
33        $crate::paste! {
34            $crate::lazy_static! {
35                pub static ref $var_name: Result<String, &'static str> = std::env::var(stringify!($env_name))
36                    .or_else(|_| std::env::var(stringify!($default_env_name)).map_err(|_| stringify!($env_name)));
37            }
38            pub fn [<$var_name:lower>]() -> &'static str {
39                $var_name.as_ref().unwrap()
40            }
41        }
42    }
43}
44
45
46#[macro_export]
47macro_rules! env_var_req {
48    ($env_name:ident $(-> $short_name:ident)?) => {
49        env_var_req!(impl $env_name, $($short_name)? $env_name);
50    };
51    (impl $env_name:ident, $var_name:ident $($extra:ident)?) => {
52        $crate::paste! {
53            $crate::lazy_static! {
54                pub static ref $var_name: Result<String, &'static str> = std::env::var(stringify!($env_name)).map_err(|_| stringify!($env_name));
55            }
56            pub fn [<$var_name:lower>]() -> &'static str {
57                $var_name.as_ref().unwrap()
58            }
59        }
60    }
61}
62
63#[macro_export]
64macro_rules! assert_req_env {
65    ($check_name_fn:ident: $($names:ident),+) => {
66        const NAMES_LEN: usize = [$(stringify!($names)),+].len();
67        pub fn $check_name_fn() -> Result<(), EnvVarErr<NAMES_LEN>> {
68            let errs = [$($names.as_ref().err().map(|e| *e)),+];
69            if errs.iter().any(Option::is_some) {
70                Err(EnvVarErr::new(errs))
71            } else {
72                Ok(())
73            }
74        }
75    };
76}
77
78pub struct EnvVarErr<const T: usize>([Option<&'static str>; T]);
79
80impl<const T: usize> EnvVarErr<T> {
81    pub fn new(inner: [Option<&'static str>; T]) -> Self {
82        Self(inner)
83    }
84}
85impl<const T: usize> Display for EnvVarErr<T> {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        self.0
88            .into_iter()
89            .flatten()
90            .enumerate()
91            .try_for_each(
92                |(idx, var_name)| if idx == 0 {
93                    write!(f, "{var_name}")
94                } else {
95                    write!(f, ", {var_name}")
96                }
97            )
98    }
99}
100impl<const T: usize> Debug for EnvVarErr<T> {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        write!(f, "{self}")
103    }
104}