env_convert/
lib.rs

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}