5 个版本 (破坏性)
0.5.0 | 2020年6月18日 |
---|---|
0.4.0 | 2020年4月3日 |
0.3.0 | 2019年10月21日 |
0.2.0 | 2018年7月31日 |
0.1.0 | 2017年12月20日 |
#249 在 配置
65,888 每月下载量
在 2 crates 中使用
75KB
1.5K SLoC
config_struct
这是一个库,可以在构建时将配置文件转换为相应的源文件。
使用方法
此库旨在在 build.rs
文件中使用,因此需要将其添加到 [build-dependencies]
。
[build-dependencies.config_struct]
version = "~0.4.0"
features = ["toml-parsing"]
默认情况下,config_struct
对标记语言不可知,因此需要包含您配置文件所使用的语言的相应功能。选项包括
json-parsing
ron-parsing
toml-parsing
yaml-parsing
构建时
现在,在您的 build.rs
文件中,添加如下代码
use config_struct::{Error, StructOptions};
fn main() -> Result<(), Error> {
config_struct::create_config(
"config.toml",
"src/config.rs",
&StructOptions::default())
}
这将处理以下 config.toml
文件
name = "Config name"
... 并生成一个类似以下的 config.rs
文件
// ...
use std::borrow::Cow;
#[derive(Debug, Clone)]
#[allow(non_camel_case_types)]
pub struct Config {
pub name: Cow<'static, str>,
}
pub const CONFIG: Config = Config {
name: Cow::Borrowed("Config name"),
};
字符串和数组通过 Cow
类型表示,这使得整个 Config 结构体要么在运行时堆分配,要么是一个编译时常量,如上所示。
支持 serde
除非您在运行时明确避免使用 serde
家族的库,否则建议使用以下选项
StructOptions {
serde_support: SerdeSupport::Yes,
generate_load_fns: true,
.. my_other_options
}
这将为您的基本结构体派生 Serialize
和 Deserialize
特性,并提供一个方便的 load()
方法来在运行时读取和解析文件。
如果您只想设置默认选项之外的其他选项,则可以使用 StructOptions::serde_default()
作为缩写。
运行时
有多种方法可以在运行时访问配置。
- 调用生成的加载函数,例如
let config = Config::load();
- 请注意,这需要上面描述的
generate_load_fns
选项。
- 请注意,这需要上面描述的
- 直接访问
CONFIG
常量,例如:let x = CONFIG.name;
- 手动反序列化配置文件,例如:
let config: Config = toml::from_str(file_contents)?
- 请注意,这要么需要上面提到的
serde_support
选项,要么需要您手动将serde::Serialize
和serde::Deserialize
添加到derived_traits
选项中。
- 请注意,这要么需要上面提到的
第一种方法推荐,因为它在发布模式下返回常量值,但在调试模式下从文件系统中加载。这为您在开发期间提供了灵活性,并在发布时提供了不可变性。
枚举
枚举生成的工作方式与结构体类似,但用于映射的键。
// build.rs
use config_struct::{Error, EnumOptions};
fn main() -> Result<(), Error> {
config_struct::create_enum(
"items.yaml",
"src/items.rs",
&EnumOptions::default())
}
上述构建脚本将处理以下 items.yaml
文件,并生成一个(未格式化的)items.rs
,如下所示:
# items.yaml
ItemOne:
- data
ItemTwo:
- more
- data
// items.rs
// ...
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Key {
ItemOne,
ItemTwo,
}
impl Key {
pub const ALL: &'static [Key] = &[Key::ItemOne, Key::ItemTwo];
}
impl Default for Key {
fn default() -> Self {
Self::ItemOne
}
}
impl std::fmt::Display for Key {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl std::str::FromStr for Key {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
const STRINGS: &'static [&'static str] = &["ItemOne", "ItemTwo"];
for (index, &key) in STRINGS.iter().enumerate() {
if key == s {
return Ok(Key::ALL[index]);
}
}
Err(())
}
}
如您所见,这提供了更多开箱即用的功能 - 其中大部分可以在 EnumOptions
中禁用。这个的目的是为了有一个小的、高效的类型,用作初始配置文件中存储的数据的键。
依赖项
~0.3–1MB
~22K SLoC