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:

rust 复制代码
#[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:

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

Such as:

rust 复制代码
        let s = Config::builder()
            .set_default("debug", true)?
            ...

But how to set a member like Database struct?

rust 复制代码
        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`

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:

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

For nested struct:

rust 复制代码
#[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())
    }
}
rust 复制代码
        let s = Config::builder()
            .set_default("database", Database::default())?
            ...
相关推荐
小灰灰搞电子1 小时前
Rust可以取代C++么?
开发语言·c++·rust
百锦再2 小时前
京东云鼎入驻方案解读——通往协同的“高架桥”与“快速路”
android·java·python·rust·django·restful·京东云
异步思考者6 小时前
Rust实战:一个内存消息队列的 Trait 驱动开发
rust
受之以蒙7 小时前
智能目标检测:用 Rust + dora-rs + yolo 构建“机器之眼”
人工智能·笔记·rust
熬了夜的程序员7 小时前
【Rust学习之路】第 0 章:理解 Rust 的核心哲学
开发语言·学习·rust
EniacCheng7 小时前
【RUST】学习笔记-环境搭建
笔记·学习·rust
禅思院7 小时前
在win10上配置 Rust以及修改默认位置问题
开发语言·前端·后端·rust·cargo·mingw64·cargo安装位置
shandianchengzi8 小时前
【记录】Rust|Rust开发相关的7个VSCode插件的介绍和推荐指数(2025年)
开发语言·vscode·rust
JPX-NO8 小时前
Rust + Rocket + Diesel构建的RESTful API示例(CRUD)
开发语言·rust·restful
林太白8 小时前
Rust01-认识安装
开发语言·后端·rust