5个稳定版本
3.2.0 | 2023年4月15日 |
---|---|
3.0.0 | 2023年3月14日 |
2.0.0 | 2022年3月31日 |
1.1.0 | 2022年2月8日 |
1.0.0 | 2022年2月7日 |
#578 在 解析器实现
1,619 每月下载量
用于 9 个crate(8个直接)
135KB
3.5K SLoC
一个具有出色错误报告和方便的 derive 宏的 KDL 文件格式解析器。
关于KDL
为了向您介绍 KDL 格式的背景,这里有一个小示例
foo 1 key="val" "three" {
bar
(role)baz 1 2
}
以下是根据 规范 和本指南描述的所有数据的注释
foo 1 "three" key="val" { ╮
─┬─ ┬ ───┬─── ────┬──── │
│ │ │ ╰───── property (can be multiple) │
│ │ │ │
│ ╰────┴────────────── arguments │
│ │
└── node name ├─ node "foo", with
│ "bar" and "baz"
bar │ being children
(role)baz 1 2 │
──┬─ │
└────── type name for node named "baz" │
} ╯
(注意,属性的顺序并不重要,以及与参数相关的属性的顺序,所以我将参数移动到交叉较少的箭头处)
用法
此库最常用的用法是使用 derive
和 [parse] 函数
#[derive(knuffel::Decode)]
enum TopLevelNode {
Route(Route),
Plugin(Plugin),
}
#[derive(knuffel::Decode)]
struct Route {
#[knuffel(argument)]
path: String,
#[knuffel(children(name="route"))]
subroutes: Vec<Route>,
}
#[derive(knuffel::Decode)]
struct Plugin {
#[knuffel(argument)]
name: String,
#[knuffel(property)]
url: String,
}
# fn main() -> miette::Result<()> {
let config = knuffel::parse::<Vec<TopLevelNode>>("example.kdl", r#"
route "/api" {
route "/api/v1"
}
plugin "http" url="https://example.org/http"
"#)?;
# Ok(())
# }
它解析为枚举 TopLevelNode
的节点向量,但如果没有声明属性和参数,也可以使用某些节点作为文档的根
#[derive(knuffel::Decode)]
struct Document {
#[knuffel(child, unwrap(argument))]
version: Option<String>,
#[knuffel(children(name="route"))]
routes: Vec<Route>,
#[knuffel(children(name="plugin"))]
plugins: Vec<Plugin>,
}
let config = parse::<Document>("example.kdl", r#"
version "2.0"
route "/api" {
route "/api/v1"
}
plugin "http" url="https://example.org/http"
"#)?;
有关允许的属性和解析模式的完整参考,请参阅 Decode 和 DecodeScalar 的描述
错误
此crate发布了漂亮的错误,如下所示
要使它们正常工作,必须在最终应用的 Cargo.toml
中启用 miette 的 "fancy" 功能
[dependencies]
miette = { version="4.3.0", features=["fancy"] }
然后,应将解析器返回的错误转换为 miette::Report 并使用调试处理程序打印。最手动的方法是
# #[derive(knuffel::Decode, Debug)]
# struct Config {}
# let file_name = "1.kdl";
# let text = "";
let config = match knuffel::parse::<Config>(file_name, text) {
Ok(config) => config,
Err(e) => {
println!("{:?}", miette::Report::new(e));
std::process::exit(1);
}
};
但通常返回 miette::Result
的函数就足够了
# use std::fs;
# #[derive(knuffel::Decode)]
# struct Config {}
use miette::{IntoDiagnostic, Context};
fn parse_config(path: &str) -> miette::Result<Config> {
let text = fs::read_to_string(path).into_diagnostic()
.wrap_err_with(|| format!("cannot read {:?}", path))?;
Ok(knuffel::parse(path, &text)?)
}
fn main() -> miette::Result<()> {
let config = parse_config("my.kdl")?;
# Ok(())
}
有关配置错误输出的其他方法的说明,请参阅 miette 指南
名称
KDL 发音为 cuddle。"Knuffel" 在荷兰语中与 cuddle 的意思相同。
许可协议
根据以下任一协议许可
- Apache License,版本 2.0,(./LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证(./LICENSE-MIT 或 http://opensource.org/licenses/MIT),任选其一。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义,您有意提交用于工作内容的任何贡献,应作为上述双重许可,不附加任何额外条款或条件。
依赖项
~4MB
~63K SLoC