3.6 KiB
envkit
envkit is a small Rust crate for reading environment variables as typed values.
It provides a minimal loader API for required values, optional values, defaults,
prefixed variable names, and simple .env-style files.
Install
Add envkit to your Cargo.toml:
[dependencies]
envkit = "0.2.1"
Quick Start
use envkit::EnvLoader;
fn main() -> Result<(), envkit::error::EnvError> {
let env = EnvLoader::new();
let port: u16 = env.get("PORT")?;
let debug: bool = env.get_or("DEBUG", false);
let app_name: String = env
.get_opt("APP_NAME")
.unwrap_or_else(|| "envkit".to_string());
println!("{app_name} listening on port {port}; debug={debug}");
Ok(())
}
API
EnvLoader::get
Reads a required environment variable and parses it into the requested type.
let env = envkit::EnvLoader::new();
let port: u16 = env.get("PORT")?;
Returns EnvError::MissingVar when the variable is not set and
EnvError::Invalid when parsing fails.
EnvLoader::get_or
Reads an environment variable and returns a fallback when the variable is missing or invalid.
let debug: bool = env.get_or("DEBUG", false);
EnvLoader::get_opt
Reads an environment variable and returns None when the variable is missing or
invalid.
let name: Option<String> = env.get_opt("APP_NAME");
EnvLoader::with_prefix
Creates a loader that prepends a prefix to every key.
let app = env.with_prefix("APP_");
let host: String = app.get("HOST")?; // reads APP_HOST
let port: u16 = app.get_or("PORT", 8080); // reads APP_PORT
EnvLoader::load_file
Loads variables from a file with one KEY=VALUE pair per line.
let env = envkit::EnvLoader::new();
env.load_file(".env")?;
Blank lines and lines starting with # are ignored. Keys and values are
trimmed before being written into the process environment.
Example file:
# .env
PORT=8080
DEBUG=true
APP_NAME=envkit
Supported Types
Built-in parsing supports:
Stringbool- signed integers:
i8,i16,i32,i64,i128,isize - unsigned integers:
u8,u16,u32,u64,u128,usize - floats:
f32,f64 Vec<T>whereTalso implementsFromEnv
Boolean values accept:
true/false1/0t/fyes/no
Lists are comma-separated and each item is trimmed before parsing:
let env = envkit::EnvLoader::new();
let ports: Vec<u16> = env.get("PORTS")?;
let flags: Vec<bool> = env.get("FEATURE_FLAGS")?;
Custom Types
Implement FromEnv for your own types when you want domain-specific parsing.
use envkit::{error::EnvError, FromEnv};
enum LogFormat {
Json,
Pretty,
}
impl FromEnv for LogFormat {
fn from_env(value: &str) -> Result<Self, EnvError> {
match value.trim().to_lowercase().as_str() {
"json" => Ok(Self::Json),
"pretty" => Ok(Self::Pretty),
other => Err(EnvError::invalid(
"LogFormat",
other,
"expected `json` or `pretty`",
)),
}
}
}
Errors
envkit returns EnvError values:
EnvError::MissingVar(key)when a required environment variable is not set.EnvError::Invalid { key, value, message }when a value cannot be parsed.EnvError::FileError { path, message }when a file cannot be read or contains an invalid line.
Examples
Run the included examples with:
cargo run --example basic
cargo run --example prefixed
The examples seed their own environment variables so they can be run directly.
Development
Run the test suite with:
cargo test