#env-var #environment #const #value #constant #items

macro const_env--value

Configure const and static items by environment variables

1 unstable release

0.1.2 Jul 25, 2020

#1741 in Procedural macros

Download history 43/week @ 2023-12-04 53/week @ 2023-12-11 69/week @ 2023-12-18 54/week @ 2023-12-25 36/week @ 2024-01-01 63/week @ 2024-01-08 68/week @ 2024-01-15 58/week @ 2024-01-22 44/week @ 2024-01-29 47/week @ 2024-02-05 72/week @ 2024-02-12 64/week @ 2024-02-19 80/week @ 2024-02-26 78/week @ 2024-03-04 78/week @ 2024-03-11 102/week @ 2024-03-18

338 downloads per month
Used in 5 crates (4 directly)

CC0 license

10KB

const_env

NOTE: This is a small fork which adds a macro for retrieving the environment variable values as an expression. It should be upstreamed, this crate is temporary and will not be updated.

Motivation

Your goal: You want to define various constants for your code at compile time based on environment variables.

Your problem: Its only possible to do this for &'static str constants in today's Rust.

const MY_STR: &'static str = env!("SOME_ENV");

You cannot similarly initialize other types such as constant u32s, bools, or other primitive types. See issues and workarounds. Eventually you will be able to do so once support for running parse and unwrap in const fn lands, but for now this crate offers an easy workaround that you can use today.

Usage

Add the dependency.

[dependencies]
const_env = "0.1"

At the top of your file import the from_env! macro.

use const_env::from_env;

Use the macro to override the value of constants based on environment variables at build time.

#[from_env]
const FOO: u32 = 123;

// This test will PASS if invoked as `FOO=456 cargo test`
#[test]
fn test() {
    assert_eq!(456, FOO);
}

By default, the macro looks for an environment variable with the same name as the constant that it is attached to.

// Use `FOO=true cargo build` to configure the value.
#[from_env]
const FOO: bool = false;

But you can specify a name explicitly too.

// Use `BAR=true cargo build` to configure the value.
#[from_env("BAR")]
const FOO: bool = false;

The expression that you assign in your source acts as a default in case the environment variable does not exist.

// If env var FOO is not set then the FOO constant will have the default value of '🦀'.
#[from_env]
const FOO: char = '🦀';

Both const and static declarations are supported.

// Both of these may be set by `FOO=abc BAZ=def cargo build`.
#[from_env]
const FOO: &'static str = "hello";
#[from_env("BAZ")]
static BAR: &'static [u8] = b"world";

Supported Types

Strings!

#[from_env]
const FOO: &'static str = "hello";

// example: `FOO=abc cargo build`
// results in:
const FOO: &'static str = "abc";

Byte strings!

#[from_env]
const FOO: &'static [u8] = b"hello";

// example: `FOO=world cargo build`
// results in:
const FOO: &'static [u8] = b"world";

Bytes!

#[from_env]
const FOO: u8 = b'';

// example: `FOO=🦀 cargo build`
// results in:
const FOO: u8 = b'🦀';

Characters!

#[from_env]
const FOO: char = '';

// example: `FOO=🦀 cargo build`
// results in:
const FOO: car = '🦀';

Integers of all shapes and sizes!

#[from_env]
const FOO: u32 = 123;
#[from_env]
const BAR: i64 = 456;
#[from_env]
const BAZ: usize = 0;

// example: `FOO=321 BAR=-456 BAZ=1usize cargo build`
// results in:
const FOO: u32 = 321;
const BAR: i64 = -456;
const BAZ: usize = 1usize;

Floats of all shapes and sizes!

#[from_env]
const FOO: f32 = 123.0;
#[from_env]
const BAR: f64 = 456.0;
#[from_env]
const BAZ: f32 = 0.0;

// example: `FOO=321.0 BAR=-456.0 BAZ=1f32 cargo build`
// results in:
const FOO: f32 = 321.0;
const BAR: f64 = -456.0;
const BAZ: f32 = 1f32;

Booleans!

#[from_env]
const FOO: bool = false;

// example: `FOO=true cargo build`
// results in:
const FOO: bool = true;

Known Limitations

  • Only top-level const and static declarations are supported.

Alternatives

  • Writing a build.rs script which looks at the env vars and generates code based on them. This is conceptually similar to how this crate works, except that this crate uses a procedural macro instead of a build script.
  • Wait for const fn to be finished, particularly control flow, so you can do env!("FOO").parse().unwrap() when assigning to const variables.

Dependencies

~1.5MB
~35K SLoC