自学内容网 自学内容网

How to set_default() using config-rs crate

How to set_default() using config-rs crate

(Jin Qing’s Column, Nov., 2024)

config is a configuration system for Rust applications.

Example of examples\hierarchical-env:

#[derive(Debug, Deserialize)]
#[allow(unused)]
struct Database {
    url: String,
}

#[derive(Debug, Deserialize)]
#[allow(unused)]
pub(crate) struct Settings {
    debug: bool,
    database: Database,
}

impl Settings {
    pub(crate) fn new() -> Result<Self, ConfigError> {
        let s = Config::builder()
            .add_source(File::with_name("examples/hierarchical-env/config/default"))
            .build()?;

        // You can deserialize (and thus freeze) the entire configuration as
        s.try_deserialize()
    }
}

ConfigBuilder::set_default sets a default value at key:

pub fn set_default<S, T>(self, key: S, value: T) -> Result<Self, ConfigError>
where
    S: AsRef<str>,
    T: Into<Value>,

Such as:

        let s = Config::builder()
            .set_default("debug", true)?
            ...

But how to set a member like Database struct?

        let s = Config::builder()
            .set_default("database", Database{url: "".into()})?
            ...

fails:

error[E0277]: the trait bound `ValueKind: From<Database>` is not satisfied
   --> examples\hierarchical-env\settings.rs:50:38
    |
50  |             .set_default("database", Database{url: "".into()})?
    |              -----------             ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<Database>` is not implemented for `ValueKind`, which is required by `Database: Into<Value>`
    |              |
    |              required by a bound introduced by this call
    |
    = help: the following other types implement trait `From<T>`:
              <ValueKind as From<&'a str>>
              ...
              <ValueKind as From<i32>>
            and 9 others
    = note: required for `Database` to implement `Into<ValueKind>`
    = note: required for `Value` to implement `From<Database>`
    = note: 1 redundant requirement hidden
    = note: required for `Database` to implement `Into<Value>`
note: required by a bound in `ConfigBuilder::<St>::set_default`
   --> D:\github\config-rs\src\builder.rs:156:12
    |
153 |     pub fn set_default<S, T>(mut self, key: S, value: T) -> Result<Self>
    |            ----------- required by a bound in this associated function
...
156 |         T: Into<Value>,
    |            ^^^^^^^^^^^ required by this bound in `ConfigBuilder::<St>::set_default`

  • https://www.reddit.com/r/rust/comments/xgbtl0/how_to_properly_use_set_default_method_in/?rdt=37431
  • https://www.reddit.com/r/rust/comments/v7744h/rust_crate_configrs_set_custom_struct_as_default/

The above links suggest to use ValueKind:

        let s = Config::builder()
            .set_default(
                "database",
                ValueKind::Table(HashMap::<String, Value>::from([("url".into(), "".into())])),
            )?
            ...

The ergonomic way is to implement From<Database> for ValueKind:

impl From<Database> for ValueKind {
    fn from(value: Database) -> Self {
        let t = HashMap::<String, Value>::from([("url".into(), value.url.into())]);
        ValueKind::Table(t)
    }
}
        let s = Config::builder()
            .set_default("database", Database { url: "".into() })?
            ...

For nested struct:

#[derive(Debug, Default, Deserialize)]
#[allow(unused)]
struct Database {
    url: String,
    other: Other,
}

#[derive(Debug, Default, Deserialize)]
#[allow(unused)]
struct Other {}

impl From<Database> for ValueKind {
    fn from(value: Database) -> Self {
        let t = HashMap::<String, Value>::from([
            ("url".into(), value.url.into()),
            ("other".into(), value.other.into()),
        ]);
        ValueKind::Table(t)
    }
}

impl From<Other> for ValueKind {
    fn from(_value: Other) -> Self {
        ValueKind::Table(HashMap::new())
    }
}
        let s = Config::builder()
            .set_default("database", Database::default())?
            ...

原文地址:https://blog.csdn.net/jq0123/article/details/143606534

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!