Skip to content
/ envy Public

envy: Deserialize environment variables into type-safe structs

License

MIT and 2 other licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE.json
BSL-1.0
LICENSE.visit_struct
Notifications You must be signed in to change notification settings

p-ranav/envy

standard license version

envy is a small header-only library to deserialize environment variables into type-safe structs.

Quick Start

Start by creating a struct where to store the values of environment variables.

#include <envy/envy.hpp>

struct ServerConfig {
  int  server_alive_interval = 45;
  bool compression           = false;
  int  compression_level     = 0;
  bool forward_x11           = true;
};
ENVY_STRUCT(ServerConfig, server_alive_interval, compression, compression_level, forward_x11);

For each field in the struct, envy will look for an environment variable with the same name in upper case, e.g., for the field named forward_x11, envy will look for an environment variable named FORWARD_X11.

Use envy::get<T>() to get a deserialized, type-safe struct.

int main() {
  auto config = envy::get<ServerConfig>();
  
  std::cout << "Server Alive Interval : " << config.server_alive_interval << "\n";
  std::cout << "Compression Enabled?  : " << std::boolalpha << config.compression << "\n";
  std::cout << "Compression Level     : " << config.compression_level << "\n";
  std::cout << "Forward X11?          : " << std::boolalpha << config.forward_x11 << "\n"; 
}

Here's the stdout of the above program:

▶ ./main
Server Alive Interval : 45
Compression Enabled?  : false
Compression Level     : 0
Forward X11?          : true

▶ SERVER_ALIVE_INTERVAL=90 COMPRESSION=1 COMPRESSION_LEVEL=9 FORWARD_X11=0 ./main
Server Alive Interval : 90
Compression Enabled?  : true
Compression Level     : 9
Forward X11?          : false

Deserialize comma-separated values

Comma-separated values can be deserialized into an std::vector:

#include <envy/envy.hpp>

struct Config {
  std::vector<int> values;
};
ENVY_STRUCT(Config, values);

int main() {
  auto config = envy::get<Config>();

  for (auto& v : config.values) {
    std::cout << v << " ";
  }
}
▶ ./main

▶ VALUES=1,2,3,4,5 ./main
1 2 3 4 5

Deserialize JSON

JSON can be deserialized into std::map, std::unordered_map or even nlohmann::json:

#include <envy/envy.hpp>

struct Config {
  std::map<std::string, int> values;
};
ENVY_STRUCT(Config, values);

int main() {
  auto config = envy::get<Config>();

  for (auto& kv : config.values) {
    std::cout << kv.first << " : " << kv.second << "\n";
  }
}
▶ ./main

▶ VALUES='{"a": 1, "b": 2, "c": 3}' ./main
a : 1
b : 2
c : 3

Application Prefix for Environment Variables

#include <envy/envy.hpp>

struct Config {
  int   foo = 0;
  float bar = 0.0f;
  bool  baz = false;
};
ENVY_STRUCT(Config, foo, bar, baz);

int main() {
  auto config = envy::get<Config>("APP_"); // prefix for env vars

  std::cout << "foo : " << config.foo << "\n";
  std::cout << "bar : " << config.bar << "\n";
  std::cout << "baz : " << std::boolalpha << config.baz << "\n";
}
▶ ./main
foo : 0
bar : 0
baz : false

▶ APP_FOO=1 APP_BAR=3.14 APP_BAZ=1 ./main
foo : 1
bar : 3.14
baz : true

Generating Single Header

python3 utils/amalgamate/amalgamate.py -c single_include.json -s .

Contributing

Contributions are welcome, have a look at the CONTRIBUTING.md document for more information.

License

The project is available under the MIT license.