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}