Skip to content

Commit

Permalink
Merge pull request #39 from YushiOMOTE/require-enum-fromstr
Browse files Browse the repository at this point in the history
Requires enum to implement FromStr
  • Loading branch information
YushiOMOTE authored Sep 13, 2024
2 parents c57814f + 7ee8867 commit 43b3f19
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 16 deletions.
35 changes: 35 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,26 @@ There are some existing crates that provide similar features but `econf` is uniq
* Containers: `Vec`, `HashSet`, `HashMap`, `Option`, `BTreeMap`, `BTreeSet`, `BinaryHeap`, `LinkedList`, `VecDeque`, `tuple`
* Containers are parsed as YAML format. See [the tests](https://github.com/YushiOMOTE/econf/blob/master/econf/tests/basics.rs).
## Enums
Since v0.3.0, econf requires enums to implement [FromStr](https://doc.rust-lang.org/std/str/trait.FromStr.html) trait. Without this implementation, your program will fail to compile. While you can write the `FromStr` implementation manually, you can alternatively use [strum](https://github.com/Peternator7/strum) crate to automatically generate it. `strum` provides several useful features, making it a generally recommended choice. See [econf/examples/strum.rs](https://github.com/YushiOMOTE/econf/tree/master/econf/examples/strum.rs) for example code.
```rust
use econf::LoadEnv;

#[derive(Debug, strum::EnumString, LoadEnv)]
#[strum(serialize_all = "kebab-case")]
enum AuthMode {
ApiKey,
BasicAuth,
#[strum(ascii_case_insensitive)]
BearerToken,
#[strum(serialize = "oauth", serialize = "OAuth")]
OAuth,
JWT,
}
```
## Nesting
Nested structs are supported.
Expand Down
15 changes: 1 addition & 14 deletions econf-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,21 +113,8 @@ fn content(name: &Ident, data: &Data) -> TokenStream2 {
Fields::Unit => {}
});

let enums0 = data.variants.iter().map(|_| &name);
let enums1 = data.variants.iter().map(|f| &f.ident);
let enums2 = data.variants.iter().map(|f| &f.ident);

quote! {
match String::default().load(path, loader).as_ref() {
#(
stringify!(#enums1) => #enums0::#enums2,
)*
"" => self,
x => {
error!("econf: couldn't find variant: {}", x);
self
}
}
loader.load_from_str(self, path)
}
}
Data::Union(_) => unimplemented!("Unions are not supported"),
Expand Down
1 change: 1 addition & 0 deletions econf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ humantime = "2.1"

[dev-dependencies]
simple_logger = "5.0"
strum = { version = "0.26", features = ["derive"] }
2 changes: 1 addition & 1 deletion econf/examples/alltypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use econf::LoadEnv;
use log::*;
use std::collections::{HashMap, HashSet};

#[derive(Debug, LoadEnv)]
#[derive(Debug, strum::EnumString, LoadEnv)]
enum X {
V1,
V2,
Expand Down
2 changes: 1 addition & 1 deletion econf/examples/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use econf::LoadEnv;
use log::*;
use std::collections::HashMap;

#[derive(Debug, LoadEnv)]
#[derive(Debug, strum::EnumString, LoadEnv)]
enum X {
V1,
V2,
Expand Down
34 changes: 34 additions & 0 deletions econf/examples/strum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use econf::LoadEnv;

#[derive(Debug, strum::EnumString, LoadEnv)]
#[strum(serialize_all = "kebab-case")]
enum AuthMode {
ApiKey,
BasicAuth,
#[strum(ascii_case_insensitive)]
BearerToken,
#[strum(serialize = "oauth", serialize = "OAuth")]
OAuth,
JWT,
}

#[derive(Debug, LoadEnv)]
struct Config {
auth_mode: AuthMode,
data: String,
passwd: String,
}

fn main() {
simple_logger::init().unwrap();

let c = Config {
auth_mode: AuthMode::ApiKey,
data: "foo".into(),
passwd: "bar".into(),
};
println!("Before loading env: {c:?}");

let c = econf::load(c, "app");
println!("After loading env: {c:?}");
}
20 changes: 20 additions & 0 deletions econf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,26 @@
//! * Containers: `Vec`, `HashSet`, `HashMap`, `Option`, `BTreeMap`, `BTreeSet`, `BinaryHeap`, `LinkedList`, `VecDeque`, `tuple`
//! * Containers are parsed as YAML format. See [the tests](https://github.com/YushiOMOTE/econf/blob/master/econf/tests/basics.rs).
//!
//! # Enums
//!
//! Since v0.3.0, econf requires enums to implement [FromStr](https://doc.rust-lang.org/std/str/trait.FromStr.html) trait. Without this implementation, your program will fail to compile. While you can write the `FromStr` implementation manually, you can alternatively use [strum](https://github.com/Peternator7/strum) crate to automatically generate it. `strum` provides several useful features, making it a generally recommended choice. See [econf/examples/strum.rs](https://github.com/YushiOMOTE/econf/tree/master/econf/examples/strum.rs) for example code.
//!
//! ```
//! use econf::LoadEnv;
//!
//! #[derive(Debug, strum::EnumString, LoadEnv)]
//! #[strum(serialize_all = "kebab-case")]
//! enum AuthMode {
//! ApiKey,
//! BasicAuth,
//! #[strum(ascii_case_insensitive)]
//! BearerToken,
//! #[strum(serialize = "oauth", serialize = "OAuth")]
//! OAuth,
//! JWT,
//! }
//! ```
//!
//! # Nesting
//!
//! Nested structs are supported.
Expand Down

0 comments on commit 43b3f19

Please sign in to comment.