3 个版本 (破坏性更新)

0.3.1 2024 年 1 月 20 日
0.2.0 2024 年 1 月 15 日
0.1.0 2024 年 1 月 14 日

#705 in 解析器实现

Download history 2636/week @ 2024-04-12 2849/week @ 2024-04-19 2632/week @ 2024-04-26 2453/week @ 2024-05-03 2264/week @ 2024-05-10 2845/week @ 2024-05-17 2926/week @ 2024-05-24 2647/week @ 2024-05-31 3088/week @ 2024-06-07 2834/week @ 2024-06-14 2894/week @ 2024-06-21 2533/week @ 2024-06-28 2664/week @ 2024-07-05 2840/week @ 2024-07-12 2780/week @ 2024-07-19 2242/week @ 2024-07-26

每月 10,858 次下载

MIT/Apache

42KB
1K SLoC

BOML

BOML 是一个为 Rust 语言的、无依赖的(几乎)零拷贝的 TOML 解析器。

快速演示

解析

BOML 使用 Toml 结构体来解析 TOML 文件并加载其根表。这可能会返回成功解析的 TOML,或者有关语法错误的详细信息。如果解析成功,则可以像使用 HashMap 一样使用 Toml 结构体从根表中获取值。

use boml::prelude::*;

fn parse_cargo_toml() {
	let source = include_str!("../Cargo.toml");
  let toml = Toml::parse(source).unwrap();
  // If you prefer, `Toml::new()` will do the same thing:
  // let toml = Toml::new(source).unwrap();

  // Get the package table from the `Cargo.toml` file
  let package = toml.get("package").unwrap();
}

类型

BOML 将 TOML 数据存储在 TomlValue 枚举中,每个类型都有一个变体。在上面的示例中,package 变量只是存储一个 TomlValue,这可以是任何 TOML 类型,对我们来说并不太有用。我们希望 package 是一个表。BOML 提供了多种便捷的方式来实现这一点

// Tables provide `get_<type>` methods, which will return the value as that type if it matches.
// If this method fails, it provides detailed error information, described below.
let package = toml.get_table("package").unwrap();
// All tables provide the `get_<type>` methods, so we can use them to get values from package, too
let name = package.get_string("name").unwrap();
assert_eq!(name, "boml");

// `TomlValue`s can be converted to one of their enum variants - this works similarly to the `.ok()` and
// `.err()` methods on `Result`s.
let package = toml.get("package").unwrap().table().unwrap();
let name = package.get("name").unwrap().string().unwrap();
assert_eq!(name, "boml");

// If you're really dedicated to boilerplate, you can also manually unwrap the enum variant.
let Some(TomlValue::Table(package)) = toml.get("package") else {
  panic!("I love boilerplate");
};

BOML 还提供了一个 TomlValueType 枚举,允许你在运行时确定值的类型。在 TomlValue 上的 .ty() 方法提供了这些信息

let package = toml.get("package").unwrap();
assert_eq!(package.ty(), TomlValueType::Table);

错误处理

BOML 中有两个错误来源:解析错误或来自表格中 get_<type> 方法之一的一个错误。这些分别使用 TomlErrorTomlGetError 类型。

TomlError,解析错误类型,存储解析错误发生处的文本范围,以及一个 TomlErrorKind,它描述了该范围内的错误类型。

TomlGetError 是表格中 get_<type> 方法之一的一个错误。当提供的键没有值时(InvalidKey)或类型不匹配时(TypeMismatch - 例如,尝试使用 get_table 获取 String 值时),会引发此类错误。一个 TypeMismatch 错误存储了实际的 TOML 值及其类型,因此如果您可能的话,仍然可以尝试使用它。

状态/待办

BOML可以解析TOML中除日期/时间/日期时间类型之外的所有内容。其原始目标是仅解析Rust配置文件,例如Cargo.toml,用于bargo

BOML还可以将技术上无效的TOML解析为有效的TOML。其当前目标是仅解析TOML,因此技术上不是有效的TOML的额外情况可能不会被捕获。

您可以通过运行toml_test测试来测试BOML与官方TOML测试套件cargo t toml_test -- --show-output)。此测试当前跳过时间类型的测试,并在无效测试通过时仅打印警告(而不是失败)。它还跳过没有有效UTF-8编码的测试(因为Rust字符串需要UTF-8)。有了这些例外,BOML能够通过toml-test套件。

为什么是"(几乎)零拷贝"?

TOML有两种字符串:基本字符串和字面字符串。字面字符串是BOML可以从文件中读取的字符串,但基本字符串可以包含转义符(例如,\n被替换为新行字符)。处理这些转义符需要复制字符串,然后用实际字符替换转义符。

BOML仅当字符串是基本字符串(由"包围)并且实际上包含转义符时才会复制和格式化字符串。字面字符串(由'包围)以及没有转义符的基本字符串不会复制。

Whatsitstandfor

是的。

无运行时依赖