env-convert 0.1.1

Conversion of environment variables with default values.
Documentation
#[cfg(test)]
mod tests;

use std::any::type_name;
use std::convert::Infallible;
use std::env;
use std::env::VarError;
use std::error::Error;
use std::ffi::OsStr;
use std::fmt::{Debug, Display, Formatter};

pub struct EnvVar {
    name: String,
    env_value: String
}

macro_rules! impl_from_envvar {
    ($($t:ty),+ $(,)?) => {
        $(
            impl From<EnvVar> for Result<$t, EnvVarConversionError> {
                fn from(value: EnvVar) -> Self {
                     match value.env_value.parse() {
                         Ok(v) => Ok(v),
                         Err(_) => Err(EnvVarConversionError {
                             value: value.env_value,
                             env_name: value.name,
                             conversion_type: type_name::<$t>(),
                         })
                     }
                }
            }
        )+
    };
}

impl From<EnvVar> for Result<String, Infallible> {
    fn from(value: EnvVar) -> Self {
        Ok(value.env_value)
    }
}

impl From<EnvVar> for String {
    fn from(value: EnvVar) -> Self { value.env_value }
}

impl_from_envvar!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, usize, isize);
impl_from_envvar!(f32, f64);

#[derive(Debug)]
pub struct EnvVarConversionError {
    pub value: String,
    pub env_name: String,
    pub conversion_type: &'static str
}

impl Display for EnvVarConversionError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "Environment conversion error. Environment variable `{}` with value '{}' count not be converted to `{}`", self.env_name, self.value, self.conversion_type)
    }
}

impl Error for EnvVarConversionError {}

pub fn get_env_var<N: AsRef<OsStr>>(name: N) -> Result<EnvVar, VarError> {
    Ok(EnvVar {
        name: name.as_ref().to_string_lossy().into_owned(),
        env_value: env::var(name)?
    })
}

pub fn get_default_env_var<N: AsRef<OsStr>, S: AsRef<str>>(name: N, default: S) -> EnvVar {
    let name_str = name.as_ref().to_string_lossy().into_owned();
    let value = env::var(name).unwrap_or_else(|_| default.as_ref().to_owned());
    EnvVar {
        name: name_str,
        env_value: value,
    }
}