rust-cli / config-rs

⚙️ Layered configuration system for Rust applications (with strong support for 12-factor applications).
https://docs.rs/config/latest/config/
Apache License 2.0
2.64k stars 214 forks source link

re-thinking: Self-describing configuration #339

Open matthiasbeyer opened 2 years ago

matthiasbeyer commented 2 years ago

I do work with @TheNeikos in an open source project where we introduced "self-describing" configuration types.

That means that we provided a derive macro that could be used on config types so that fetching an explanation of what that type meant is possible. The derive-macro used the doc comments for that.

We should explore how it would be possible to add something like this to this crate.


As a quick example for some imaginary crate:

#[derive(Debug, config::ConfigDescription)]
struct MyConfig {
    /// The URL to fetch data from
    url: url::Url,

    /// The verbosity while fetching
    verbosity: Verbosity,
}

#[derive(Debug, config::ConfigDescription)]
enum Verbosity {
    /// be loud
    Loud,
    /// be louder than normal
    Louder,
    /// be as loud as possible
    Loudest,
}

// somewhere:
MyConfig::config_description() // returns ConfigDescription object that can be rendered for the user in a nice way

Resuling in approximately this output:

[table]

The URL to fetch data from
url: An URL
    An UTF-8 encoded String

The verbosity while fetching
verbosity: Verbosity
    one of:
        "load" - be loud
        "louder" - be louder than normal
        "loudest" - be as loud as possible    
dbofmmbt commented 2 years ago

With a derive-macro, it would probably be possible to print the structure of a config input for any format supported. It could be useful while defining the config struct and easily knowing how to "feed" it.

IDK, just an idea I had :smile:

xinslu commented 2 years ago

I would love to work on this issue, if possible! I should say I'm still fairly new to Rust, but I think writing a derive macro would be a good first issue!

matthiasbeyer commented 2 years ago

Feel free to try this! A friend of mine (@theneikos) implemented it in another project, so I know it is definitively possible! :laughing: