Build a config structure from environment variables in Rust without boilerplate

Related tags

Configuration yasec
Overview

Yasec

Build Status License

Yet another stupid environment config (YASEC) creates settings from environment variables. (Envconig-rs fork)

Features

  • Nested configuration structure.
  • Inferring of an environment variable name. If a configuration field has name password then it gets value from environment variable PASSWORD. If a configuration field is inside another structure and it has path db.password it gets its value from variable DB_PASSWORD.
  • Custom types.
  • Option type is optional.
  • Prefix of variables.

I implemented everything what I require when I develop an application. Feel free to open an issue of a feature you miss as well as a pull request.

Macro attributes

  • from - name of an environment variable which provides a field value. Name of the field and name of the parent structures are ignored.
  • default - default value of a field if an environment variable doesn't exist. If the environment variable exist but has invalid value an error returns.

Usage

You can achieve this with the following code without boilerplate:

, mode: Mode, } pub enum Mode { Client, Server, } impl Yasec for Mode { fn parse(s: &str) -> Result> { match s { "CLIENT" => Ok(Self::Client), "SERVER" => Ok(Self::Server), _ => Err(yasec::ParseError::new(s).into()), } } } fn main() { // Assuming the following environment variables are set std::env::set_var("DB_HOST", "127.0.0.1"); std::env::set_var("DB_PORT", "5432"); std::env::set_var("API_KEY", "0912xn819b8s1029s"); std::env::set_var("API_SECRET", "zyYWn5pPtLcDSaFWQEu0nf1cf0eYNN8j"); std::env::set_var("MODE", "SERVER"); std::env::remove_var("LISTEN_PORT"); std::env::remove_var("CALLBACK_URL"); // Initialize config from environment variables or terminate the process. let config = Config::init().unwrap(); assert_eq!(config.db.host, "127.0.0.1"); assert_eq!(config.db.port, 5432); assert_eq!(config.vendor.key, "0912xn819b8s1029s"); assert_eq!(config.vendor.secret, "zyYWn5pPtLcDSaFWQEu0nf1cf0eYNN8j"); assert_eq!(config.listen_port, 8080); assert_eq!(config.callback_url, None); match config.mode { Mode::Server => (), _ => panic!("Unexpected value of Mode"), } } ">
#[macro_use]
extern crate yasec_derive;
extern crate yasec;

use std::error::Error as StdError;
use yasec::Yasec;

#[derive(Yasec)]
pub struct DB {
    pub host: String,
    pub port: u16,
}

#[derive(Yasec)]
pub struct Vendor {
    #[yasec(from = "API_KEY")]
    pub key: String,
    #[yasec(from = "API_SECRET")]
    pub secret: String,
}

#[derive(Yasec)]
pub struct Config {
    db: DB,
    vendor: Vendor,
    #[yasec(default = 8080)]
    listen_port: u16,
    callback_url: Option<String>,
    mode: Mode,
}

pub enum Mode {
    Client,
    Server,
}

impl Yasec for Mode {
    fn parse(s: &str) -> Result<Self, Box<dyn StdError>> {
        match s {
            "CLIENT" => Ok(Self::Client),
            "SERVER" => Ok(Self::Server),
            _ => Err(yasec::ParseError::new(s).into()),
        }
    }
}

fn main() {
    // Assuming the following environment variables are set
    std::env::set_var("DB_HOST", "127.0.0.1");
    std::env::set_var("DB_PORT", "5432");
    std::env::set_var("API_KEY", "0912xn819b8s1029s");
    std::env::set_var("API_SECRET", "zyYWn5pPtLcDSaFWQEu0nf1cf0eYNN8j");
    std::env::set_var("MODE", "SERVER");
    std::env::remove_var("LISTEN_PORT");
    std::env::remove_var("CALLBACK_URL");

    // Initialize config from environment variables or terminate the process.
    let config = Config::init().unwrap();

    assert_eq!(config.db.host, "127.0.0.1");
    assert_eq!(config.db.port, 5432);
    assert_eq!(config.vendor.key, "0912xn819b8s1029s");
    assert_eq!(config.vendor.secret, "zyYWn5pPtLcDSaFWQEu0nf1cf0eYNN8j");
    assert_eq!(config.listen_port, 8080);
    assert_eq!(config.callback_url, None);
    match config.mode {
        Mode::Server => (),
        _ => panic!("Unexpected value of Mode"),
    }
}

Running tests

Tests do some manipulation with environment variables, so to prevent flaky tests they have to be executed in a single thread:

cargo test -- --test-threads=1

License

Licensed under MIT

You might also like...
vault client using jwt authentication that define environment variables from vault secrets before executing into something else

envlt envlt, like env, allows you to define environment variables and then execute into something else, but instead of static values, it uses using si

Envful is a CLI tool that verifies the presence of environment variables
Envful is a CLI tool that verifies the presence of environment variables

Envful is a CLI tool that verifies the presence of environment variables. It looks inside your .env file and the host system. You can use it to run any process while ensuring all the variables are set.

Set Shell Environment Variables across multiple shells with a single configuration file.

Xshe – Cross-Shell Environment Vars xshe allows for setting Shell Environment Variables across multiple shells with a single TOML configuration file.

Loads environment variables into your structs in one shot.
Loads environment variables into your structs in one shot.

econf Loads environment variables into your structs in one shot. econf allows to override struct fields with environment variables easily. This is use

Deserialize (potentially nested) environment variables into your custom structs
Deserialize (potentially nested) environment variables into your custom structs

envious allows you to deserialize your serde enabled structs from environment variables. See it in action: use serde::{Deserialize, Serialize}; #[der

A Modern And Secure CLI Tool For Managing Environment Variables
A Modern And Secure CLI Tool For Managing Environment Variables

Envio is a command-line tool that simplifies the management of environment variables across multiple profiles. It allows users to easily switch between different configurations and apply them to their current environment

🕺 Run React code snippets/components from your command-line without config

Run React code snippets/components from your command-line without config.

Build Java applications without fighting your build tool. Drink some espresso.
Build Java applications without fighting your build tool. Drink some espresso.

Espresso Build Java applications without fighting your build tool. Drink some espresso. Features Modern Look & Feel Command line interface inspired by

Rust crate: Overloaded Literals to construct your datatypes without boilerplate and with compile-time validation.

overloaded_literals   Overloaded Literals to construct your datatypes without boilerplate and with compile-time validation. Features Compile-time vali

⚙️ A curated list of static analysis (SAST) tools for all programming languages, config files, build tools, and more.
⚙️ A curated list of static analysis (SAST) tools for all programming languages, config files, build tools, and more.

This repository lists static analysis tools for all programming languages, build tools, config files and more. The official website, analysis-tools.de

Bootstrap your MEV bot strategies with a simple boilerplate to build on top of.

MEV Template Designed by DeGatchi. Bootstrap your MEV bot strategies with a simple boilerplate to build on top of. How To Use This Template I wrote an

A cargo subcommand to fetch the $OUT_DIR environment variable from build scripts

cargo-outdir A cargo subcommand to fetch the $OUT_DIR variable from build scripts. This is extremely useful to inspect the output of automatically gen

The auto-managed -sys crate for Apple platforms using bindgen directly from build environment

apple-sys Apple platforms have a rather monotonous programming environment compared to other platforms. On several development machines, we will depen

Dependency lockfiles for a reproducible build environment 📦🔒

repro-env Imagine you had a tool that takes a config like this: # repro-env.toml [container] image = "rust:1-alpine3.18" and turns it into something l

Automatically build a Rust module tree from the project directory structure

Hypermod An even lazier version of automod and supermod. Searches the src/ directory recursively for .rs files, then builds a module tree using the di

Rust crate that provides a convenient macro to quickly plot variables.
Rust crate that provides a convenient macro to quickly plot variables.

Debug Plotter This crate provides a convenient macro to quickly plot variables. Documentation For more information on how to use this crate, please ta

Fast, initializable, and thread safe static variables

tagged_cell Fast, initializable, and thread safe static variables Overview Borrows the excellent ZST based tagging implementation (linked below) to gu

Command line tool to convert env variables beginning with user to a htpasswd file

envhtp This command line tool converts environment variables whose keys start with "user_" into htpasswd compatible username/password pairs. The goal

A simple crate, that protects some variables from being modified by memory tampering tools.

Crate: protected_integer A simple crate, that protects some variables from being modified by memory tampering tools. Usage Add this crate to dependenc

Owner
null
Your next config manager, written in rust

confy Your next config manager, written in rust Based on uncomfyhalomacro/hmph but written for .ini files instead of json :) Getting started Take a lo

Krishna Ramasimha 2 Nov 3, 2021
Uclicious is a flexible reduced boilerplate configuration framework.

Uclicious What is Uclicious Usage Raw API Derive-driven Validators Type Mapping Supported attributes (#[ucl(..)]) Structure level Field level Addition

Andrey Cherkashin 14 Aug 12, 2022
This repository is an experimental WebAssembly build of the [ymfm] Yamaha FM sound cores library.

This repository is an experimental WebAssembly build of the [ymfm] Yamaha FM sound cores library.

hiromasa 36 Dec 25, 2022
A Rust library for processing application configuration easily

Configure me A Rust library for processing application configuration easily About This crate aims to help with reading configuration of application fr

Martin Habovštiak 48 Dec 18, 2022
⚙️ Layered configuration system for Rust applications (with strong support for 12-factor applications).

config-rs Layered configuration system for Rust applications (with strong support for 12-factor applications). Set defaults Set explicit values (to pr

Ryan Leckey 1.8k Jan 9, 2023
cfg-rs: A Configuration Library for Rust Applications

cfg-rs: A Configuration Library for Rust Applications Major Features One method to get all config objects, see get. Automatic derive config object, se

Daniel YU 20 Dec 16, 2022
An easy to configure wrapper for Rust's clippy

An easy to configure wrapper for Rust's clippy

Eric Seppanen 46 Dec 19, 2022
`haproxy_autconfd` is a daemon that automatically assembles a HAProxy config and restarts HAProxy if the config changes

haproxy_autconfd Welcome to haproxy_autconfd ?? haproxy_autconfd is a daemon that automatically assembles a HAProxy config and restarts HAProxy if the

null 0 Nov 9, 2021
A Rust-based Garry's Mod module for fetching environment variables.

gm_environ Using Environment Variables in Garry's Mod. Installation Download a copy of the module from the releases (or compile from source) Move the

Joshua Piper 2 Jan 4, 2022
Rust Lambda Extension for any Runtime to preload SSM Parameters as 🔐 Secure Environment Variables!

?? Crypteia Rust Lambda Extension for any Runtime to preload SSM Parameters as Secure Environment Variables! Super fast and only performaned once duri

Custom Ink 34 Jan 7, 2023