Crates.io | envoke |
lib.rs | envoke |
version | 0.3.0 |
created_at | 2025-02-23 11:07:11.103511+00 |
updated_at | 2025-03-26 16:21:26.135919+00 |
description | A simple and ergonomic way to load environment variables into struct fields. |
homepage | |
repository | https://github.com/sbr075/envoke-rs |
max_upload_size | |
id | 1566255 |
size | 44,954 |
Envoke is a simple and ergonomic way to load environment variables into struct fields with minimal setup. With support for multiple ways to define environment variables with additional fallbacks, default values, custom parsing, validation, and nested structs for a cleaner interface.
Designed to be flexible and reduce boilerplate, all to make it easier to manage environment variables in your application.
.env
file with the dotenv
attribute—works on both structs and enums.try_parse_fn
attribute lets you use fallible parsing functions. Just like parse_fn
, but it accepts a Result
.Read more here!
Flexible Environment Variable Naming
Customize naming conventions with support for multiple environments, renaming, prefixes, and suffixes.
Versatile Default Values
Define defaults through type-based values, direct assignments, or function return values.
Pre-Assignment Parsing
Convert values into complex types before field assignment for enhanced data handling.
Comprehensive Validation
Validate values before and/or after assignment to ensure data integrity.
Structured Data Support
Seamlessly work with nested structs, enums, or standalone enums.
Built-in Sequence & Map Parsing
Effortlessly parse sequence and map-formatted strings for structured data.
Add to your Cargo.toml
[dependencies]
envoke = "0.3.0"
use std::time::Duration;
use anyhow::Context;
use envoke::{Envoke, Error, Fill};
#[derive(Debug, Fill)]
#[fill(rename_all = "SCREAMING_SNAKE_CASE")]
struct Prod {
#[fill(env)]
api_port: u16,
}
#[derive(Debug, Fill)]
#[fill(rename_all = "SCREAMING_SNAKE_CASE")]
struct Development {
#[fill(env)]
api_port: u16,
}
#[derive(Debug, Fill)]
#[fill(rename_all = "UPPERCASE")]
enum Mode {
Production(Production),
Development(Development),
}
fn above_thirty(secs: &u64) -> anyhow::Result<()> {
if *secs < 30 {
anyhow::bail!("connect timeout cannot be less than 30 seconds, found {secs} second(s)")
}
Ok(())
}
fn to_duration(secs: u64) -> Duration {
Duration::from_secs(secs)
}
#[derive(Debug, Fill)]
#[fill(rename_all = "SCREAMING_SNAKE_CASE")]
struct Environment {
#[fill(nested)]
mode: Mode,
#[fill(env, default = Duration::from_secs(30))]
#[fill(parse_fn = to_duration, arg_type = u64, validate_fn(before = above_thirty))]
connect_timeout: Duration,
}
fn main() -> anyhow::Result<()> {
let env =
Environment::try_envoke().with_context(|| "An error occurred while loading environment");
...
}