Derive Macro FromEnv

Source
#[derive(FromEnv)]
{
    // Attributes available to this derive:
    #[from_env]
}
Expand description

The derive(FromEnv) macro.

This macro generates a FromEnv implementation for the struct it is applied to. It will generate a from_env function that loads the struct from the environment. It will also generate an inventory function that returns a list of all environment variables that are required to load the struct.

The macro also generates a ____EnvError type that captures errors that can occur when trying to create an instance of the struct from environment variables. This error type is used in the FromEnv trait implementation.

§FromEnv vs FromEnvVar

While FromEnvVar deals with loading simple types from the environment, FromEnv is for loading complex types. It builds a struct from the environment, usually be delegating each field to a FromEnvVar or FromEnv implementation.

When using the derive macro, the props of the struct must implement FromEnv or FromEnvVar. Props that implement FromEnv contain all the information needed to load the struct from the environment. Props that implement FromEnvVar need additional information via attributes.

§Attributes

The macro supports the following attributes:

  • var = "": The name of the environment variable. This is required if the prop implements FromEnvVar and forbidden if the prop implements FromEnv.
  • desc = "": A description of the environment variable. This is required if the prop implements FromEnvVar and forbidden if the prop implements FromEnv.
  • optional: Marks the prop as optional. This is currently only used in the generated fn inventory, and is informational.
  • infallible: Marks the prop as infallible. This means that the prop cannot fail to be parsed after the environment variable is loaded.
  • skip: Marks the prop as skipped. This means that the prop will not be loaded from the environment, and will be generated via Default::default() instead.

§Conditions of use

There are a few usage requirements:

  • Struct props MUST implement either FromEnvVar or FromEnv.
  • If the prop implements FromEnvVar, it must be tagged as follows:
    • var = "ENV_VAR_NAME": The environment variable name to load.
    • desc = "description": A description of the environment variable.
  • If the prop is an Option<T>, it must be tagged as follows:
    • optional
  • If the prop’s associated error type is Infallible, it must be tagged as follows:
    • infallible
  • If used within this crate (init4_bin_base), the entire struct must be tagged with #[from_env(crate)] (see the SlotCalculator for an example).

§Examples

The following example shows how to use the macro:

use init4_bin_base::utils::from_env::{FromEnv};

#[derive(Debug, FromEnv)]
pub struct MyCfg {
    #[from_env(var = "COOL_DUDE", desc = "Some u8 we like :o)")]
    pub my_cool_u8: u8,

    #[from_env(var = "CHUCK", desc = "Charles is a u64")]
    pub charles: u64,

    #[from_env(
        var = "PERFECT",
        desc = "A bold and neat string",
        infallible,
    )]
    pub strings_cannot_fail: String,

    #[from_env(
        var = "MAYBE_NOT_NEEDED",
        desc = "This is an optional string",
        optional,
        infallible,
    )]
    maybe_not_needed: Option<String>,
}

#[derive(Debug, FromEnv)]
pub struct MyBiggerCfg {
    #[from_env(var = "BIGGGG_CONFIGGGG", desc = "A big config", infallible)]
    pub big_config: String,

    // Note that becuase `MyCfg` implements `FromEnv`, we do not need to
    // specify the `var` and `desc` attributes.
    pub little_config: MyCfg,
}

// The [`FromEnv`] trait is implemented for the struct, and the struct can
// be loaded from the environment.
if let Err(missing) = MyBiggerCfg::check_inventory() {
    println!("Missing environment variables:");
    for var in missing {
        println!("{}: {}", var.var, var.description);
    }
}

This will generate a FromEnv implementation for the struct, and a MyCfgEnvError type that is used to represent errors that can occur when loading from the environment. The error generated will look like this:

pub enum MyCfgEnvError {
    MyCoolU8(<u8 as FromEnvVar>::Error),
    Charles(<u64 as FromEnvVar>::Error),
    // No variants for infallible errors.
}

This macro generates an implementation of the FromEnv trait for a struct. See the documenetation in init4_bin_base for more details.