#config-parser #config-file #build-config #build #parser-generator #parser

config_struct

在构建时从配置文件创建结构定义

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配置

Download history 9907/week @ 2024-03-14 15096/week @ 2024-03-21 8987/week @ 2024-03-28 15114/week @ 2024-04-04 11045/week @ 2024-04-11 17710/week @ 2024-04-18 10385/week @ 2024-04-25 11106/week @ 2024-05-02 17728/week @ 2024-05-09 33226/week @ 2024-05-16 17218/week @ 2024-05-23 15197/week @ 2024-05-30 19193/week @ 2024-06-06 18990/week @ 2024-06-13 16744/week @ 2024-06-20 6973/week @ 2024-06-27

65,888 每月下载量
2 crates 中使用

CC0 许可证

75KB
1.5K SLoC

config_struct

这是一个库,可以在构建时将配置文件转换为相应的源文件。

Build Status Crates.io Docs.rs

使用方法

此库旨在在 build.rs 文件中使用,因此需要将其添加到 [build-dependencies]

[build-dependencies.config_struct]
version = "~0.4.0"
features = ["toml-parsing"]

默认情况下,config_struct 对标记语言不可知,因此需要包含您配置文件所使用的语言的相应功能。选项包括

  1. json-parsing
  2. ron-parsing
  3. toml-parsing
  4. 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
}

这将为您的基本结构体派生 SerializeDeserialize 特性,并提供一个方便的 load() 方法来在运行时读取和解析文件。

如果您只想设置默认选项之外的其他选项,则可以使用 StructOptions::serde_default() 作为缩写。

运行时

有多种方法可以在运行时访问配置。

  1. 调用生成的加载函数,例如 let config = Config::load();
    • 请注意,这需要上面描述的 generate_load_fns 选项。
  2. 直接访问 CONFIG 常量,例如:let x = CONFIG.name;
  3. 手动反序列化配置文件,例如:let config: Config = toml::from_str(file_contents)?
    • 请注意,这要么需要上面提到的 serde_support 选项,要么需要您手动将 serde::Serializeserde::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