5 个版本
0.2.4 | 2020年1月23日 |
---|---|
0.2.3 | 2020年1月21日 |
0.2.2 | 2020年1月16日 |
0.2.1 | 2020年1月16日 |
0.2.0 | 2020年1月16日 |
#1969 在 解析器实现
76KB
1.5K SLoC
KeyTree
KeyTree
是一种优雅的标记语言,旨在将可读信息转换为Rust数据结构。它设计得快速,以减少认知负荷,并且易于为自己的类型实现。它不依赖于其他crate,因此编译速度快。其格式如下
hobbit:
name: Frodo Baggins
age: 60
friends:
hobbit:
name: Bilbo Baggins
age: 111
hobbit:
name: Samwise Gamgee
age: 38
这样数据可以递归。此外,使用路径如 hobbit::friends::hobbit
可以轻松引用一组数据。
此库不遵循标准的Rust错误处理模式。如果有解析错误,它将崩溃;如果将值转换为Rust类型的操作中出错,它也将崩溃(并带有友好的错误消息)。如果您不希望出现这种情况,您需要将其在自己的线程/进程中运行。
数据格式规则
-
缩进具有意义,为4个空格,相对于顶级键。由于缩进相对于顶级键,因此可以整齐地对代码中的嵌入式字符串进行对齐。
-
每行可以是空行、只有空白、注释、键或键/值对。
-
存在键和值。键/值对看起来像
name: Frodo
用于 struct
字段和 enum
变体。
键引用其下缩进的一行中的子键或子键/值对,例如
hobbit:
name: Frodo
hobbit 引用结构体或枚举的名称。这样,数据简单映射到Rust数据结构。
- 如果一个键有多个具有相同键的子键,它将形成一个集合,例如
hobbit:
name: Frodo
name: Bilbo
是一个hobbits的集合。
-
键不能包含冒号
:
,但必须紧随其后。 -
值是 ':' 和空白之间的所有字符以及行尾之间的所有字符。值在两端都进行了空白修剪。
-
注释需要在行的开头有
//
。例如
// comment
hobbit:
name: Frodo
示例
Into
从 KeyTree
到 Rust 类型的自动实现已经为 Vec<T>
、Option<T>
和基本的 Rust 类型提供。可以使用类型推断将 KeyTree
文本自动转换为这些数据类型。函数 at()
返回一个遍历 KeyTree
类型的迭代器,可用于为您的类型实现 Into
。以下示例应涵盖90%的使用场景。
use keytree::KeyTree;
use keytree::parser::KeyTreeBuilder;
#[derive(Debug)]
struct Hobbit {
name: String,
age: u32,
friends: Vec<Hobbit>,
nick: Option<String>,
}
impl<'a> Into<Hobbit> for KeyTree<'a> {
fn into(self) -> Hobbit {
Hobbit {
name: self.at("hobbit::name"),
age: self.at("hobbit::age"),
friends: self.at("hobbit::friends::hobbit"),
nick: self.op("hobbit::nick"),
}
}
}
fn main() {
let s = r#"
hobbit:
name: Frodo Baggins
age: 98
friends:
hobbit:
name: Bilbo Baggins
age: 176
hobbit:
name: Samwise Gamgee
age: 66
nick: Sam"#;
let core = KeyTreeBuilder::parse(s);
let hobbit: Hobbit = KeyTree::from_core(&core).into();
dbg!(&hobbit);
}
详细信息
我们将详细查看示例中第几行发生的事情:
friends: self.at("hobbit::friends::hobbit"),
在 Into
特性实现中,我们希望 Bilbo Baggins 和 Samwise Gamgee 成为 Frodo 的朋友。我们使用路径 "hobbit::friends::hobbit"
来指定他们在 KeyTree
字符串中的位置,这指向树中的两个分支(两个霍比特人)。与 op()
函数不同,at()
函数要求这些分支存在。Rust 推断它们需要转换为 Hobbit
结构体中指定的类型 Vec<Hobbit>
。实际上,KeyTree
为 Into
的 Vec<T>
实现提供了支持。事实上,at()
函数提供了一个霍比特人的迭代器,该迭代器被 Vec<T>
实现使用。