这是我在Rust中的第一个项目,我觉得我错过了一些简单的东西。
我试图创建一个简单的Web API守护进程,它将接收JSON的POST请求,解析JSON并使用配置文件中提供的凭据发送电子邮件。这个问题的90%都很容易。我正在努力解决“在运行时解析配置文件”的问题。
我成功地使用hyper和letter接收JSON并发送电子邮件。但我希望这个守护进程可以在服务器上配置,而不是在构建时(像大多数Linux / Unix守护进程一样)。我已经认真地遵循了这里。
我创建了一个配置模块,声明了一个结构体,并使用
我认为我已经将我的问题归纳为一个核心问题:如何读取和解析配置文件,然后将值“克隆”到我的结构体中?特别是考虑到这些值的大小在运行时是未知的...
例如:
任何想法?建议?
我试图创建一个简单的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
}
}
和 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);
}
任何想法?建议?
toml
的 crate 来完成解析。我看到你已经在使用 serde,toml
也依赖它 :) 既然你似乎只需要写一次,没有理由不在主函数中构造一个Arc<Config>
,通过克隆Arc
而不需要任何锁来以不可变方式共享它。 - user11877195