environs
Typed environment variable resolution with fallback key chains and dotenv loading.
Built because every env config crate is either too magic or too verbose.
Quick start
use env;
let port: u16 = env!?;
let db: String = env!?;
let debug: = env!?;
Macro
The env! macro injects the caller's source location into errors so you know exactly where a lookup failed.
| Syntax | Behaviour |
|---|---|
env!("KEY") |
required; error if missing |
env!("KEY1", "KEY2") |
cascade — first set key wins |
env!(..., default = val) |
typed fallback value |
env!(..., default_str = "…") |
string fallback, parsed at call time |
env!(..., default_fn = || expr) |
lazy fallback, not evaluated if key is found |
env!(..., resolve_with = |raw| …) |
custom parser; bypasses FromEnvStr |
Builder API
For when you want to construct the lookup in steps:
use Var;
// required
let port: u16 = new.get?;
// typed default
let port: u16 = new.default.get?;
// string default (parsed at call time)
let port: u16 = new.default_str.get?;
// lazy default
let port: u16 = new.default_fn.get?;
// custom parser
let hosts: = new
.resolve_with?;
Dotenv
// convenience functions
load?; // load .env (or $DOTENV_PATH); skip if missing; don't override
load_override?; // same but overrides existing vars
load_path?; // explicit path; fail if missing; don't override
load_override_path?; // explicit path; fail if missing; override
// builder — chain multiple files, mix optional and required
new
.path // skip if missing
.path // skip if missing
.require // fail if missing
.override_existing // replace vars already in the environment
.load?;
Supported types
bool, all numeric primitives, String, PathBuf, Option<T>, Vec<T> (comma-separated), and chrono date/time types (feature chrono).
Implement FromEnvStr on your own type to hook into the full resolution pipeline including cascades, defaults, and error location.
Errors
Errors include the source file and line where env!() was called:
src/config.rs:14: PORT: expected u16, got 'banana': invalid digit found in string