derive_from_env 1.0.1

Extract type safe structured data from environment variables with procedural derive macros
Documentation
use std::{net::Ipv6Addr, path::PathBuf, str::FromStr};

use derive_from_env::FromEnv;
use temp_env::with_vars;

#[derive(Debug, PartialEq)]
enum AuthMethod {
    Bearer,
    XAPIKey,
}

impl FromStr for AuthMethod {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "Bearer" => Ok(AuthMethod::Bearer),
            "X-API-Key" => Ok(AuthMethod::XAPIKey),
            _ => Err("Invalid auth method".into()),
        }
    }
}

#[derive(Debug, PartialEq, FromEnv)]
struct AuthConfig {
    auth_method: AuthMethod,
    api_key: String,
}

#[derive(Debug, PartialEq, FromEnv)]
struct ServiceConfig {
    addr: Ipv6Addr,
    #[from_env(default = "8080")]
    port: u16,
    #[from_env(var = "EXT_SERVICE_URL")]
    base_url: String,
}

#[derive(Debug, PartialEq, FromEnv)]
#[from_env(prefix = "APP_")]
struct AppConfig {
    #[from_env(flatten)]
    service: ServiceConfig,
    #[from_env(flatten, no_prefix)]
    auth: AuthConfig,
    log_file: Option<PathBuf>,
    #[from_env(rename = "IS_PROD")]
    is_production: bool,
}

fn main() {
    with_vars(
        vec![
            ("APP_SERVICE_ADDR", Some("0:0:0:0:0:0:0:0")),
            ("EXT_SERVICE_URL", Some("http://myservice.com/api")),
            ("APP_AUTH_METHOD", Some("Bearer")),
            ("APP_API_KEY", Some("api-key")),
            ("APP_IS_PROD", Some("true")),
        ],
        || {
            let app_config = AppConfig::from_env().unwrap();
            assert_eq!(
                app_config,
                AppConfig {
                    service: ServiceConfig {
                        addr: Ipv6Addr::from_str("0:0:0:0:0:0:0:0").unwrap(),
                        port: 8080,
                        base_url: "http://myservice.com/api".into()
                    },
                    auth: AuthConfig {
                        auth_method: AuthMethod::Bearer,
                        api_key: "api-key".into()
                    },
                    log_file: None,
                    is_production: true,
                }
            )
        },
    )
}