用到的库
figment clap once_cell
从参数读取
use crate::config::Config;
#[derive(Parser, Serialize, Deserialize)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
#[clap(short, long, default_value = "tbot.toml", env("TG_BOT_CONF_PATH"))]
pub conf_path: PathBuf,
#[command(flatten)]
pub conf: Config,
}
#[command(flatten)] 用来给clap拉平结构体
Config结构
use crate::{cli::Cli, error::BotError}
pub static CONFIG: Lazy<Config> = Lazy::new(|| {
let args = Cli::parse();
let conf = args.conf;
let path = args.conf_path;
match Config::figment(&path, conf) {
Ok(conf) => conf,
Err(e) => {
eprintln!("failed to load config {}", e);
exit(1);
}
}
});
#[derive(Debug, Args, Serialize, Deserialize)]
pub struct Config {
#[clap(flatten)]
pub tgbot: TgBot,
#[clap(flatten)]
pub log: LogLevel,
}
#[derive(Debug, Args, Serialize, Deserialize)]
pub struct TgBot {
#[clap(long = "tgbot-token")]
#[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<String>,
}
#[derive(Debug, Args, Serialize, Deserialize)]
pub struct LogLevel {
#[clap(long = "log-level")]
#[serde(skip_serializing_if = "Option::is_none")]
pub level: Option<Log>,
}
#[derive(Debug, ValueEnum, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Log {
Info,
Warn,
Debug,
Error,
Trace,
}
impl Config {
pub fn figment(path: &Path, conf: Config) -> Result<Self, BotError> {
let config = Figment::new()
.merge(Toml::file(path))
.merge(Env::prefixed("TG_BOT_").split("_"))
.merge(Serialized::defaults(conf))
.extract()?;
Ok(config)
}
}
#[serde(skip_serializing_if = "Option::is_none")] 用来跳过为None值时序列化,避免None覆盖掉上一层的配置
Comments NOTHING