#document #serialization

kdl

面向文档的KDL解析器和API。允许格式化/空白字符/注释保留解析和修改KDL文本。

12个稳定版本 (5个主要版本)

5.0.0-alpha.12023年4月1日
5.0.0-alpha.02022年12月5日
4.6.0 2022年10月9日
4.3.0 2022年6月11日
0.0.0 2020年12月11日

#49 in 解析器实现

Download history 2658/week @ 2024-03-14 2910/week @ 2024-03-21 2666/week @ 2024-03-28 2506/week @ 2024-04-04 2758/week @ 2024-04-11 3169/week @ 2024-04-18 3465/week @ 2024-04-25 4063/week @ 2024-05-02 4270/week @ 2024-05-09 3607/week @ 2024-05-16 3023/week @ 2024-05-23 2977/week @ 2024-05-30 2467/week @ 2024-06-06 2361/week @ 2024-06-13 2333/week @ 2024-06-20 1893/week @ 2024-06-27

9,415 每月下载量
用于 36 个crate(27个直接使用)

Apache-2.0

170KB
4K SLoC

kdl

kdl 是KDL文档语言的“面向文档”解析器和API,KDL文档语言是一种基于节点、便于人类使用的配置和序列化格式。与基于serde的实现不同,此crate在编辑时以及插入或更改具有自定义格式的值时都保留格式。这对于处理由人类维护的KDL文件最有用。

您可以将此crate视为 toml_edit,但它是为KDL设计的。

如果您不关心格式或程序性操作,您可能需要查看 knuffelkaydle,它们用于serde(或类似serde)解析。

示例

use kdl::KdlDocument;

let doc_str = r#"
hello 1 2 3

world prop="value" {
    child 1
    child 2
}
"#;

let doc: KdlDocument = doc_str.parse().expect("failed to parse KDL");

assert_eq!(
    doc.get_args("hello"),
    vec![&1.into(), &2.into(), &3.into()]
);

assert_eq!(
    doc.get("world").map(|node| &node["prop"]),
    Some(&"value".into())
);

// Documents fully roundtrip:
assert_eq!(doc.to_string(), doc_str);

控制格式化

默认情况下,所有内容都使用默认格式创建。您可以手动解析项目以提供自定义表示、注释等。

let node_str = r#"
  // indented comment
  "formatted" 1 /* comment */ \
    2;
"#;

let mut doc = kdl::KdlDocument::new();
doc.nodes_mut().push(node_str.parse().unwrap());

assert_eq!(&doc.to_string(), node_str);

KdlDocumentKdlNodeKdlEntryKdlIdentifier 都可以通过这种方式进行解析和管理。

查询引擎

kdl 包含一个用于 KQL 的查询引擎,它允许您使用类似CSS选择器的语法从文档中选择节点。

查询可以从 KdlDocumentKdlNode 中进行,语义大致相同。

use kdl::KdlDocument;

let doc = r#"
a {
    b 1
    c 2
    d 3 {
        e prop="hello"
    }
}
"#.parse::<KdlDocument>().expect("failed to parse KDL");

let results = doc.query("a > b").expect("failed to parse query");
assert_eq!(results, Some(&doc.nodes()[0].children().unwrap().nodes()[0]));

let results = doc.query_get("e", "prop").expect("failed to parse query");
assert_eq!(results, Some(&"hello".into()));

let results = doc.query_get_all("a > []", 0).expect("failed to parse query").collect::<Vec<_>>();
assert_eq!(results, vec![&1.into(), &2.into(), &3.into()]);

错误报告

KdlError实现了miette::Diagnostic,并可以在使用miette::Result"fancy"功能标志时显示详细的、格式化的诊断信息。

# Cargo.toml
[dependencies]
miette = { version = "x.y.z", features = ["fancy"] }
fn main() -> miette::Result<()> {
    "foo 1.".parse::<kdl::KdlDocument>()?;
    Ok(())
}

这将显示类似的消息

Error:
  × Expected valid value.
   ╭────
 1 │ foo 1.
   ·     ─┬
   ·      ╰── invalid float
   ╰────
  help: Floating point numbers must be base 10, and have numbers after the decimal point.

特性

属性

允许存在具有相同名称的多个属性,并且所有重复的属性都将被保留,这意味着这些文档将正确往返。当使用node.get()/node["key"] &公司时,将返回具有该名称的最后一个属性值。

数字

KDL本身没有指定数字的特定表示形式,接受几乎所有有效的数字,无论大小如何。这意味着以下几点

  • 没有小数点的数字被解释为 [u64]。
  • 有小数点的数字被解释为 [f64]。
  • 计算结果为f64::INFINITYf64::NEG_INFINITY或NaN的浮点数将按原样在值中表示,而不是原始数字。
  • 类似的限制也适用于溢出的 [u64] 值。
  • 除非你使用KdlDocument::fmt,否则将保留这些数字的原始表示,在这种情况下,将丢弃原始表示,并在序列化时使用实际值。

许可证

此存储库中的代码受Apache-2.0许可证保护。

依赖项

~1.8–2.6MB
~44K SLoC