rok-config-macros 0.6.0

Proc-macro internals for rok-config (#[derive(Config)])
Documentation
  • Coverage
  • 100%
    3 out of 3 items documented0 out of 2 items with examples
  • Size
  • Source code size: 26.6 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 331.85 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 5s Average build duration of successful builds.
  • all releases: 8s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • ateeq1999

rok-config-macros

Proc-macro implementation of #[derive(Config)] for rok-config typed environment variable loading.

Part of the Rok Framework — a full-stack Rust web framework built on Axum 0.8 and SQLx 0.8.

crates.io docs.rs MIT

Features

  • #[derive(Config)] generates from_env() and from_env_file() implementations from struct field annotations
  • #[env("VAR_NAME")] maps a field to an environment variable — missing required fields are collected before failing
  • #[env("VAR_NAME", default = "value")] provides a fallback when the variable is absent
  • #[env("VAR_NAME", secret)] suppresses the field value in Debug output to prevent log leakage
  • Nested struct support: a field with a type that implements Config is recursively loaded
  • Compile-time detection of duplicate #[env] variable names within the same struct
  • Clear ConfigError::Missing(Vec<String>) if any required variables are absent at runtime

Installation

[dependencies]
rok-config-macros = "0.2"

This crate is re-exported by rok-config. Prefer using rok-config directly:

rok-config = "0.2"

Quick Start

use rok_config_macros::Config;

#[derive(Debug, Config)]
pub struct ServerConfig {
    #[env("HOST", default = "0.0.0.0")]
    pub host: String,

    #[env("PORT", default = "3000")]
    pub port: u16,

    #[env("WORKER_THREADS", default = "4")]
    pub worker_threads: usize,

    #[env("SHUTDOWN_TIMEOUT_SECS", default = "30")]
    pub shutdown_timeout: u64,
}

let config = ServerConfig::from_env()?;
println!("Binding {}:{}", config.host, config.port);

Core API

What the macro generates

// Input:
#[derive(Config)]
pub struct AppConfig {
    #[env("DATABASE_URL")]
    pub database_url: String,

    #[env("PORT", default = "3000")]
    pub port: u16,

    #[env("API_KEY", secret)]
    pub api_key: String,
}

// Generated (illustrative):
impl rok_config::Config for AppConfig {
    fn from_env() -> Result<Self, rok_config::ConfigError> {
        dotenvy::dotenv().ok();
        let mut missing = Vec::new();

        let database_url = std::env::var("DATABASE_URL")
            .map_err(|_| missing.push("DATABASE_URL"))
            .unwrap_or_default();

        let port = std::env::var("PORT")
            .unwrap_or_else(|_| "3000".into())
            .parse::<u16>()
            .map_err(|_| rok_config::ConfigError::Parse("PORT", "u16"))?;

        let api_key = std::env::var("API_KEY")
            .map_err(|_| missing.push("API_KEY"))
            .unwrap_or_default();

        if !missing.is_empty() {
            return Err(rok_config::ConfigError::Missing(
                missing.into_iter().map(String::from).collect()
            ));
        }
        Ok(Self { database_url, port, api_key })
    }
}

// Secret field: Debug impl prints "[REDACTED]" instead of the value
impl std::fmt::Debug for AppConfig {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("AppConfig")
            .field("database_url", &self.database_url)
            .field("port", &self.port)
            .field("api_key", &"[REDACTED]")
            .finish()
    }
}

Supported field types

Rust type Parsed from
String Raw env var string
u8, u16, u32, u64, usize Parsed integer
i8, i16, i32, i64, isize Parsed signed integer
f32, f64 Parsed float
bool "true" / "1"true, "false" / "0"false
Option<T> None when var is absent, Some(parsed) when present
std::time::Duration Parsed from seconds as u64
Any type implementing Config Recursively loaded

Integration

rok-config-macros is a proc-macro implementation detail of rok-config. All macros are accessible through rok-config with no additional dependencies required in application code.

use rok_config::Config;  // re-exports the derive macro from rok-config-macros

License

MIT