-
-
Notifications
You must be signed in to change notification settings - Fork 45
Description
💡 Feature description
Personally I would like to be able to easily print out my config in a bash format.
Then I could copy one of the config's env vars from my app's output, change the env var and restart my binary.
Others may want to output their config's env vars in a YAML-like syntax and change them in their kubernetes config.
To provide those use cases with a simple and straight-forward solution, I propose to add the following function to envy:
pub fn to_vec<T: Serialize>(value: &T) -> Result<Vec<(String, String)>> { ... }
💻 Basic example
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug, Default)]
struct Config {
foo: u16,
bar: String,
}
for (key, value) in envy::to_vec(&Config::default())? {
println!("{key}={value:?}");
}
// stdout:
// FOO="0"
// BAR=""
Alternatives
Use std::fmt::Debug instead
This has the following downsides:
- Fields aren't SCREAMING_SNAKE_CASE and it's not feasible to output a specific format with Debug.
- If you have a password field or other secret, you can no longer use
derive(Debug)
.
With serde you could use#[serde(skip_serializing)]
.
Write a custom Serializer or fn to_custom_format
for every format instead
I think for simple formats writing a Serializer is more complicated than a function using to_vec.
Add a fn to_iter
instead
pub fn to_iter<T: Serialize>(value: &T) -> impl Iterator<Item = Result<(String, String)>> + '_ { ... }
I really like this solution, because it is very flexible.
At the least this alternative should be a candidate to add in the future as well.
Implementing this function without using a std::vec::IntoIter
is a bit awkward because the Serialize trait does not seem like it's designed for this kind of step-wise serialization to an Iterator.
Printing an Iterator<Item = Result<(String, String)>>
similar to the example above is a bit more complicated:
for result in envy::to_iter(&Config::default())? {
let (key, value) = result?;
println!("{key}={value:?}");
}
or when ignoring Err values:
for (key, value) in envy::to_iter(&Config::default()).filter_map(Result::ok) {
println!("{key}={value:?}");
}
Not adding anything to envy
There's definitely an argument to keep envy as simple as possible.
I'm really curious, what other people think about this idea.
Maybe there are simpler solutions that I've overlooked.