#env-var #macro-derive #environment #macro #env #derive #proc-macro

derive_from_env

Extract type safe structured data from environment variables with procedural derive macros

3 releases

0.1.2 Jul 31, 2024
0.1.1 Jul 29, 2024
0.1.0 Jul 29, 2024

#302 in Configuration

Download history 28/week @ 2024-09-13 8/week @ 2024-09-20 5/week @ 2024-09-27 8/week @ 2024-10-04 24/week @ 2024-10-11 10/week @ 2024-10-18 6/week @ 2024-10-25 14/week @ 2024-11-01 6/week @ 2024-11-08 20/week @ 2024-11-22 31/week @ 2024-11-29

58 downloads per month

GPL-3.0-only

17KB

derive_from_env

Extract type safe structured data from environment variables with procedural derive macros. Currently based on the FromStr trait.

Usage

  • Add derive_from_env to your project's dependencies:
[dependencies]
derive_from_env = "0.1.1"
  • Usage example:
use std::net::{IpAddr, Ipv4Addr};
use std::str::FromStr;
use derive_from_env::FromEnv;

#[derive(Debug, PartialEq, FromEnv)]
struct ServiceConfig {
    api_key: String,
    #[from_env(var = "EXT_SERVICE_URL")]
    base_url: String,
}

#[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)]
#[derive(FromEnv)]
struct AuthConfig {
    #[from_env(from_str)]
    auth_method: AuthMethod,
    api_key: String,
}

#[derive(Debug, PartialEq, FromEnv)]
struct AppConfig {
    #[from_env(default = "0.0.0.0")]
    addr: IpAddr,
    port: Option<u16>,
    external_service: ServiceConfig,
    #[from_env(no_prefix)]
    auth: AuthConfig 
}

fn main() {
    std::env::set_var("EXTERNAL_SERVICE_API_KEY", "api-key");
    std::env::set_var("EXT_SERVICE_URL", "http://external.service/api");
    std::env::set_var("PORT","8080");
    std::env::set_var("AUTH_METHOD","Bearer");
    std::env::set_var("API_KEY","api-key");
    let app_config = AppConfig::from_env().unwrap();
    assert_eq!(app_config, AppConfig {
        port: Some(8080),
        addr: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
        external_service: ServiceConfig {
            api_key: "api-key".into(),
            base_url: "http://external.service/api".into() 
        },
        auth: AuthConfig {
            auth_method: AuthMethod::Bearer,
            api_key: "api-key".into()
        }
    });
}

In the future...

  • serde support via a new attribute from_serde (usefull for chrono's types)

Dependencies

~0.6–1MB
~23K SLoC