rust - 如何编写一个通用函数,用于从 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
我对这个问题还有其他问题:
- 中的生命周期会发生什么
read_common
?反序列化的字符串也是短暂的,这个实现是怎么编译的?我想这里面隐藏着一些技巧#[derive(Deserialize)]
。 - 为什么
toml::from_str
要为其输入变量和输出类型赋予相同的生命周期?对我来说,一旦反序列化完成,输出不应该引用输入字符串,那么为什么方法声明中有生命周期?
解决方案
推荐阅读
- r - table() 输出到具有列名的数据框
- java - 如何将 SoapResponse 转换为 pojos(Java 类)和将类对象转换为 Soap 请求
- .htaccess - 没有推荐人时阻止图像(热链接)(也阻止我自己的域)
- javascript - 为什么 require() 返回模块导出的“未完成副本”而不是对它的引用(循环依赖)?
- c++ - 使用 std:array 通过模板非类型参数初始化 Boost 直方图轴?
- kubernetes - 将 helm chart 的 sysctl 参数列入白名单
- javascript - 如何在 Javascript 中获取所有 cookie?
- statistics - Discord stats bot 添加旧的统计信息以嵌入
- r - 将增量计数器添加到 R 中的数据帧
- javascript - 当我打印formData时,输入文件的内容总是不确定的,为什么?反应JS