5 releases

0.1.22 Jun 14, 2023
0.1.21 Jun 13, 2023
0.1.2 Jun 13, 2023
0.1.1 Jun 11, 2023
0.1.0 Jun 11, 2023

#1950 in Procedural macros

36 downloads per month
Used in create-ruxt-app

MIT license

30KB
330 lines

env-extract

The env-extract crate provides convenient methods of extracting environment variables into different data types.

The crate includes two proc macros: ConfigStruct and EnvVar, which can be used to derive traits and implement automatic extraction of values from environment variables.

Usage

To use the EnvVar and ConfigStruct macros, add env-extract as a dependency in your Cargo.toml file:

[dependencies]
env-extract = "0.1.22"

Then, in your Rust code, import the procedural macros by adding the following line:

use env_extract::{EnvVar, ConfigStruct};

ConfigStruct Macro

The ConfigStruct macro is applied to structs and derives the ConfigStruct trait. This trait allows for the easy retrieval of a struct from environment variables by pulling each field from the environment variables by name. The following types are valid for fields of a struct:

  • String
  • bool
  • u8, u16, u32, u64, u128
  • i8, i16, i32, i64, i128
  • f32, f64
  • An enum that derives EnvVar

The ConfigStruct macro supports the following attributes on the fields in the struct:

  • default: Sets a default value for the field. If this is not provided, the macro will panic if the environment variable is not set.
  • env_var: Sets the name of the environment variable to use for this field. If this is not provided, the macro will use the name of the field in uppercase as the environment variable name.
  • enumerated: Identifies an enum that implements the EnvVar trait. The macro will parse the environment variable to the enum type.

EnvVar Macro

The EnvVar macro is applied to enums and implements the EnvVar trait, which provides a .get() method to retrieve a value of type T from an environment variable. The macro parses the environment variable to the enum type.

The EnvVar macro requires one of the following conditions to be met for the enum:

  • A variant called "Invalid", which will be returned if the environment variable does not match any of the variants.
  • A variant marked with #[default], which will be returned if the environment variable does not match any of the variants.
  • The enum to be marked with #[panic_on_invalid], which will panic if the environment variable does not match any of the variants.

The EnvVar macro allows for the following attributes on the enum itself:

  • #[env_var = "FOO"]: Set a custom environment variable name to search for. Defaults to the name of the enum in uppercase.
  • #[panic_on_invalid]: Panics if a valid variant is not found.
  • #[case(convert = "[uppercase|lowercase|exact|any]")]: Converts all environment variable values to a specific case before comparing them to map the valid variant. This attribute is overwritten if the variant also contains this attribute.

The EnvVar macro also supports the following attributes on the enum variants:

  • #[case = "[uppercase|lowercase|exact|any]"]: Specifies case conversion for the annotated enum variant. The uppercase and lowercase options convert the environment variable value to uppercase or lowercase before comparing it to the variant name. The exact option compares the environment variable value to the variant name without any case conversion. The any option converts both the environment variable value and the variant name to lowercase before comparing them.
  • #[default]: Specifies the default enum variant.
  • #[ignore_variant]: Ignores the annotated enum variant when checking for a match.

Example Usage

use env_extract::{ConfigStruct, EnvVar};

#[derive(Debug, EnvVar)]
#[var_name = "DATABASE_TYPE"]
#[panic_on_invalid]
#[case(convert = "lowercase")]
enum DatabaseType {
    Postgres,
    Mysql,
    Sqlite,
}

#[derive(ConfigStruct, Debug)]
struct Config {
    db_host: String,
    db_port: u16,
    use_tls: bool,

    #[enumerated]
    db_type: DatabaseType,
}

fn main() {
    std::env::set_var("DB_HOST", "localhost");
    std::env::set_var("DB_PORT", "5432");
    std::env::set_var("USE_TLS", "true");
    std::env::set_var("DATABASE_TYPE", "postgres");

    let config = Config::get();

    assert_eq!(config.db_host, "localhost");
    assert_eq!(config.db_port, 5432);
    assert_eq!(config.use_tls, true);
    assert!(matches!(config.db_type, DatabaseType::Postgres));
}

In the example above, the ConfigStruct macro is used to derive the ConfigStruct trait for the Config struct, enabling easy retrieval of values from environment variables. The EnvVar trait is derived for the DatabaseType enum using the EnvVar macro, allowing the extraction of the enum variant from the "DATABASE_TYPE" environment variable. The environment variable values are parsed and converted according to the specified case conversions. Finally, the Config struct is populated with values retrieved from environment variables, and assertions are used to validate the extracted values.

Dependencies

~1.5MB
~37K SLoC