MCPcopy Index your code
hub / github.com/TheNeikos/envious

github.com/TheNeikos/envious @v0.3.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.3.0 ↗ · + Follow
71 symbols 119 edges 10 files 11 documented · 15%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

envious cover image

Bors enabled Crates.io Docs.rs

envious allows you to deserialize your serde enabled structs from environment variables.

See it in action:

```rust,no_run use serde::{Deserialize, Serialize};

[derive(Serialize, Deserialize, Debug)]

enum StaircaseOrientation { Left, Right, }

[derive(Serialize, Deserialize, Debug)]

struct Config { target_temp: f32, automate_doors: bool,

staircase_orientation: StaircaseOrientation,

}

let config: Config = envious::Config::default().build_from_env().expect("Could not deserialize from env");


With the following environment variables:

```bash
export target_temp=25.0
export automate_doors=true
export staircase_orientation=Left

it will parse it from the environment and give you a Rust struct you can use in your application.

Note: The environment variables are case insensitive by default! This can be modified using the [Config::case_sensitive] method.

envious also supports the ability to only take in prefixed environment variables via the [Config::with_prefix] method. This will strip it before processing them further.

Getting Started

To use envious simply add it to your Cargo.toml with:

cargo add envious

and deserialize from your environment with [Config::default] and then [Config::build_from_env]!

⚠️ Current Shortcomings

  • Tuple Enum Variants can currently not be longer than one element!
  • Deserializing where a null in other formats is required is currently not possible
  • See #12 for more details

How deserialization works

The mapping between environment variables and the serde model is as follows:

Nested fields are seperated by a provided separator.

This can be modified by using the [Config::with_separator] and defaults to __ (double underscore). For example, if you have the following struct:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct Radiator {
    min_temp: f32,
    max_temp: f32,
}

#[derive(Serialize, Deserialize)]
struct Config {
    target_temp: f32,
    radiator: Option<Radiator>
}

You can deserialize Config with the following variables:

export target_temp=21.0
export radiator__min_temp=15.0
export radiator__max_temp=30.0

Arrays are serialized using nested fields

Arrays are represented as anonymous structs, with the 'fields' being the individual elements.

A more complex example could look like this:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
enum Material {
    Wood,
    Plastic,
}

#[derive(Serialize, Deserialize)]
struct Door {
    width: f32,
    height: f32,
    material: Material,
}

#[derive(Serialize, Deserialize)]
struct House {
    age: u32,
    entrance_doors: Vec<Door>,
}

Now, to deserialize a House we can set the following variables:

export age=120
export entrance_doors__0__width=100
export entrance_doors__0__height=100
export entrance_doors__0__material="Wood"
export entrance_doors__1__width=200
export entrance_doors__1__height=120
export entrance_doors__1__material="Plastic"
export entrance_doors__foo__width=400
export entrance_doors__foo__height=20
export entrance_doors__foo__material="Plastic"

For details on ordering, see [Config::ordered_arrays].

Unit enums variants (without fields), are serialized from strings

As you can see in the example above, the Material enum gets simply deserialized from the name of the variant. Be careful about upper/lower case if you have enabled case sensitivity via [Config::case_sensitive]. With this enabled, Serde requires that the case is exactly the same!

Complex enum variants are serialzed just like structs

Per default serde uses external tagging for more complicated enum variants. Tuple enums are currently only supported with a single value.

To see what this means, lets take this enum as an example:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
enum Shape {
    Rectangle { width: f32, height: f32 },
    Circle(f32),
    Nothing,
}

#[derive(Serialize, Deserialize)]
struct Config {
    expected_shape: Shape,
}

To deserialize Config here, we can use the following variables:

export expected_shape__Rectangle__width=50.0
export expected_shape__Rectangle__height=10.0

// OR

export expected_shape__Circle=15.0

// OR

export expected_shape=Nothing

Any of these sets of variables would give you the expected outcome.

Should you change the tagging of your struct, be sure to adapt the given variables.

License

envious is licensed under MIT or Apache 2.0, as you wish.

Contributing

To contribute to envious you can:

  • Open up issues with ideas, remarks, bug reports, etc...
  • Fork and implement new features and send them in as pull requests
  • Leave it a Star and spread the word! ;)

  • When sending in a PR, make sure to add a 'Signed-Off-By' to certify that you wrote or are authorized to send in the code

Core symbols most depended-on inside this repo

build_from_iter
called by 22
src/config.rs
case_sensitive
called by 7
src/config.rs
with_prefix
called by 3
src/config.rs
create_parser
called by 3
src/config.rs
into_deserializer
called by 2
src/value.rs
deserialize_map
called by 2
src/value.rs
maybe_coerce_case
called by 2
src/config.rs
insert_at
called by 1
src/value.rs

Shape

Method 23
Class 20
Function 20
Enum 8

Languages

Rust100%

Modules by API surface

src/value.rs19 symbols
src/config.rs14 symbols
src/lib.rs13 symbols
tests/prefix_env.rs5 symbols
tests/complex_env.rs5 symbols
tests/case_sensitivity.rs4 symbols
tests/simple_env.rs3 symbols
tests/hashmap.rs3 symbols
tests/failure.rs3 symbols
src/error.rs2 symbols

For agents

$ claude mcp add envious \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact