1#[cfg(test)]
2mod tests;
3
4use std::any::type_name;
5use std::convert::Infallible;
6use std::env;
7use std::env::VarError;
8use std::error::Error;
9use std::ffi::OsStr;
10use std::fmt::{Debug, Display, Formatter};
11
12pub struct EnvVar {
13 name: String,
14 env_value: String
15}
16
17macro_rules! impl_from_envvar {
18 ($($t:ty),+ $(,)?) => {
19 $(
20 impl From<EnvVar> for Result<$t, EnvVarConversionError> {
21 fn from(value: EnvVar) -> Self {
22 match value.env_value.parse() {
23 Ok(v) => Ok(v),
24 Err(_) => Err(EnvVarConversionError {
25 value: value.env_value,
26 env_name: value.name,
27 conversion_type: type_name::<$t>(),
28 })
29 }
30 }
31 }
32 )+
33 };
34}
35
36impl From<EnvVar> for Result<String, Infallible> {
37 fn from(value: EnvVar) -> Self {
38 Ok(value.env_value)
39 }
40}
41
42impl From<EnvVar> for String {
43 fn from(value: EnvVar) -> Self { value.env_value }
44}
45
46impl_from_envvar!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, usize, isize);
47impl_from_envvar!(f32, f64);
48
49#[derive(Debug)]
50pub struct EnvVarConversionError {
51 pub value: String,
52 pub env_name: String,
53 pub conversion_type: &'static str
54}
55
56impl Display for EnvVarConversionError {
57 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58 write!(f, "Environment conversion error. Environment variable `{}` with value '{}' count not be converted to `{}`", self.env_name, self.value, self.conversion_type)
59 }
60}
61
62impl Error for EnvVarConversionError {}
63
64pub fn get_env_var<N: AsRef<OsStr>>(name: N) -> Result<EnvVar, VarError> {
65 Ok(EnvVar {
66 name: name.as_ref().to_string_lossy().into_owned(),
67 env_value: env::var(name)?
68 })
69}
70
71pub fn get_default_env_var<N: AsRef<OsStr>, S: AsRef<str>>(name: N, default: S) -> EnvVar {
72 let name_str = name.as_ref().to_string_lossy().into_owned();
73 let value = env::var(name).unwrap_or_else(|_| default.as_ref().to_owned());
74 EnvVar {
75 name: name_str,
76 env_value: value,
77 }
78}