首页 > 解决方案 > 如何编写一个通用函数,用于从 TOML 反序列化多个输出类型?

问题描述

我编写了一个从 TOML 文件创建配置对象的实用程序方法:

pub fn read_common(path: &str) -> Result<Config> {
    let content = read_file(path);
    toml::from_str(&content?).map_err(|e| {
        Error::new(
            ErrorKind::InvalidData,
            format!(
                "Parsing failed at line {:?}, col {:?}",
                e.line_col().map(|p| p.0),
                e.line_col().map(|p| p.1)
            ),
        )
    })
}

Config是一个简单的可反序列化结构:

#[derive(Deserialize)]
pub struct DatabaseConfig {
    pub host: String,
    pub port: u16,
    pub database: String,
    pub user: String,
    pub password: String,
}

#[derive(Deserialize)]
pub struct Config {
    pub database: DatabaseConfig,
}

这编译并运行良好(应该如此,因为这几乎是从toml crate 的文档中复制粘贴的)。

我有多个配置文件,每个配置文件都有对应的匹配结构,所以我想泛化我的read_common方法(在所有其他情况下重用相同的错误处理)。

我写了这个:

pub fn read<'de, T>(path: &str) -> Result<T>
where
    T: Deserialize<'de>,
{
    let content = read_file(path);
    toml::from_str(&content?).map_err(|e| {
        Error::new(
            ErrorKind::InvalidData,
            format!(
                "Parsing failed at line {:?}, col {:?}",
                e.line_col().map(|p| p.0),
                e.line_col().map(|p| p.1)
            ),
        )
    })
}

T是反序列化产生的配置类型。我需要让它扩展Deserialize<'..>,所以我需要在这里度过一生,但完整的签名toml::from_str

pub fn from_str<'de, T>(s: &'de str) -> Result<T, Error>
where
    T: de::Deserialize<'de>,

据我了解,我的输入字符串应该具有与生成的反序列化对象相同(或更长)的生命周期。当然,它在我的实现中没有,因为它的生命周期在我的read方法结束时结束。借用检查器因此抱怨 ( borrowed value does not live long enough on &content?) 并且此实现无法编译。

如何编写适用于多种输出类型的通用read版本?read_common

我对这个问题还有其他问题:

标签: rust

解决方案


推荐阅读