7 configuration runtime lifetime ownership rust
这是我在 Rust 中的第一个项目,我认为我错过了一些简单的东西。
我正在尝试创建一个简单的 Web API 守护程序,它将接收 JSON 的 POST、解析 JSON,并使用配置文件中提供的凭据发送电子邮件。90% 的问题都很简单。我正在努力解决“在运行时解析配置文件”的问题。
我成功地使用 hyper 和 letter 接收 JSON 并发送电子邮件。但我希望这个守护进程可以在服务器上配置,而不是在构建时配置(像大多数 Linux / Unix 守护进程一样)。我一直孜孜不倦地走过这里。
我创建了一个配置模块,声明了一个结构,并用于lazy_static!{}存储配置结构的初始版本。
我想我已经将问题归结为一个核心问题:如何读取和解析配置文件,然后将值克隆到我的结构中?特别是考虑到这些值的大小在运行时无法得知......
例如src/config.rs
use std::sync::RwLock;
use serde::Deserialize;
use std::fs;
use std::io::prelude::*;
#[derive(Debug, Deserialize, Clone, Copy)]
pub struct RimfireCfg {
pub verbose: u8,
/* web api server config */
pub listen_address: &'static str,
/* mail server config */
pub mailserver: &'static str,
pub port: u16,
pub user: &'static str,
pub password: &'static str,
}
lazy_static! {
pub static ref CONFIG: RwLock<RimfireCfg> = RwLock::new(
RimfireCfg {
verbose: 0,
listen_address: "127.0.0.1:3000",
mailserver: "smtp-mail.outlook.com",
port: 587,
user: "",
password: "",
}
);
}
impl RimfireCfg {
pub fn init() -> Result<(), i32> {
let mut w = CONFIG.write().unwrap();
/* read the config file */
let _lcfg: RimfireCfg =
toml::from_slice(&fs::read("rimfire.toml").unwrap()).unwrap();
// this is clearly wrong ...
*w.listen_address = _lcfg.listen_address.clone();
dbg!(*w);
Ok(())
}
pub fn clone_config() -> RimfireCfg {
let m = CONFIG.read().unwrap();
*m
}
}
Run Code Online (Sandbox Code Playgroud)
和src/main.rs:
#[macro_use]
extern crate lazy_static;
mod config;
use config::RimfireCfg;
fn main() {
let a = RimfireCfg::clone_config();
dbg!(a);
RimfireCfg::init().unwrap();
let a = RimfireCfg::clone_config();
dbg!(a);
}
Run Code Online (Sandbox Code Playgroud)
有什么想法吗?建议?
你的结构应该存储Strings。Strings 是可变且可增长的——与 s 不同,您可以将文件中的数据读入其中&'static str。&'static strs 通常仅适用于常量字符串文字。我认为使用Strings 应该可以让您的示例以最小的调整工作。
此外,您可以用来std::mem::swap()一次编写整个配置。这也更有效,因为它不需要克隆字符串。
RwLock我认为如果您希望配置成为全局变量,则全局静态是合理的。或者,正如 Sahsahae 的评论中那样,您可以避免全局状态并将 an 传递Arc<RimfireCfg>给任何使用它的东西。这通常更干净。
| 归档时间: |
|
| 查看次数: |
6065 次 |
| 最近记录: |