Configuration lib用于以符合人体工程学的方式进行配置处理
我正在编写一个用于加载和处理应用程序配置的公共库,Configuration lib用于以符合人体工程学的方式进行配置处理,configuration,rust,Configuration,Rust,我正在编写一个用于加载和处理应用程序配置的公共库, 使用 我试图让它尽可能符合人体工程学的用户,但似乎无法找出它 我的图书馆: impl RunEnv { fn to_string(&self) -> String { match self { RunEnv::Production => "prod".to_string(), RunEnv::Dev => "dev".to_string(),
使用 我试图让它尽可能符合人体工程学的用户,但似乎无法找出它 我的图书馆:
impl RunEnv {
fn to_string(&self) -> String {
match self {
RunEnv::Production => "prod".to_string(),
RunEnv::Dev => "dev".to_string(),
RunEnv::Staging => "stag".to_string(),
}
}
}
impl FromStr for RunEnv {
type Err = String;
fn from_str(s: &str) -> Result<RunEnv, String> {
match s {
"dev" => Ok(RunEnv::Dev),
"stag" => Ok(RunEnv::Staging),
"prod" => Ok(RunEnv::Production),
_ => Err(format!("Could not parse {:?}", s)),
}
}
}
#[derive(Debug, StructOpt)]
#[structopt(name = "CLI Options", about = "Common CLI options for running applications")]
pub struct Arguments {
/// Run in a specific environment mode: dev, stag, prod.
// short and long flags (-e, --env) will be deduced from the field's name
#[structopt(short, long, default_value = "dev")]
pub env: RunEnv,
}
pub trait LoadConfig {
fn new() -> Result<Config, ConfigError>{
const PACKAGE_NAME: &'static str = env!("CARGO_PKG_NAME");
let mut s = Config::new();
let args = Arguments::from_args();
let mut conf_path = String::new();
match args.env {
RunEnv::Production => {
conf_path = format!("/path/to/config/{}/config.toml", PACKAGE_NAME);
}
RunEnv::Staging => {
conf_path = format!("/path/to/config/{}/config.toml", PACKAGE_NAME);
}
RunEnv::Dev => {
conf_path = "tests/config.toml".to_string();
}
}
// Start off by merging in the "default" configuration file
s.merge(File::with_name(&conf_path))?;
// Add in the current environment
// Default to 'dev' env
s.set("run_mode", args.env.to_string())?;
Ok(s)
}
}
这是我的问题,我试图“隐藏”.unwrap().try_into().unwrap()代码>分开
因此,lib用户只需要定义他的setting.rs
并运行let conf:Settings=Settings::new()
如果我将.try_into()
移动到一个trait中,那么我会遇到一个错误,我找不到解决方法:
| s.try_into()
| ^^^^^^^^ the trait `_IMPL_DESERIALIZE_FOR_Configuration::_serde::Deserialize<'_>` is not implemented for `config::config::Config`
| s.尝试()
|^^^^^^^^^^特性`“为配置实现反序列化::\u serde::反序列化为惯例,新建
函数是构建实例的方法,必须是结构的固有方法,
直接在类型上可用的方法
在您的示例中,您试图将new
定义为特征默认方法。
如果可能,签名应为:
pub trait LoadConfig {
fn new() -> Self {
}
}
这样的特质方法是不可能实现的,因为特质对Self
具体类型一无所知
要遵循此约定,最好将LoadConfig::new
trait方法重命名为其他方法:
pub trait LoadConfig {
fn load() -> Result<Config, ConfigError>;
}
请注意,一个健壮的实现不应该unwrap
,而应该更明确地管理配置错误 谢谢您的回答,您不是想为设置编写impl LoadConfig
?如果可能的话,我会尽量保留trait中的所有逻辑和错误处理,因为配置加载在任何地方都是一样的,我讨厌在每个应用程序(impl部分)中都有相同的代码。不,你需要一个新的固有方法或一种构建应用程序结构的方法,而且不可能使用默认的trait方法。我已经更新了答案,希望能有所帮助。新impl中没有太多逻辑,它只是一个示例,config应该作为参数ecc传递。ecc。
pub trait LoadConfig {
fn new() -> Self {
}
}
pub trait LoadConfig {
fn load() -> Result<Config, ConfigError>;
}
impl Settings {
fn new() -> Settings {
let config = Settings::load().unwrap(); // TBD: manage errors
let port: u32 = config.get("port").unwrap_or("8080").parse().unwrap();
Settings {
server: Server {
port: port,
address: config.get("address").unwrap_or("localhost").to_owned()
},
run_mode: None
}
}
}