10 个版本 (4 个重大更改)
0.5.0 | 2023年4月7日 |
---|---|
0.4.1 | 2023年2月25日 |
0.3.1 | 2023年2月20日 |
0.2.1 | 2023年2月12日 |
0.1.0 | 2023年1月31日 |
#773 在 解析器实现
每月137 次下载
225KB
4K SLoC
cborpath-rs
cborpath 是一个用 Rust 编写的 CBORPath 引擎。
CBORPath
CBORPath 是基于 CBOR 的 JSONPath 的适配,基于 JSONPath 互联网草案
语法摘要
路径
一个路径表达式是一个 CBOR 数组
,当它应用于一个 CBOR
值(即参数)时,选择零个或多个参数的节点,并将这些节点作为节点列表输出。
一个路径始终以一个标识符开始
- 一个根标识符(
$
)用于绝对路径, - 一个当前节点标识符(
@
)用于相对路径。相对路径总是在过滤器上下文中使用。
然后是一个或多个 段
。
语法 | 描述 |
---|---|
["$", <段>] |
由段组成的绝对路径 它始终以根标识符( $ )开始 |
["@", <段>] |
由段组成的相对路径 它始终以当前节点标识符( @ )开始 |
段
段
将对输入值应用一个或多个选择器,并将结果连接成一个节点列表。
语法 | 描述 |
---|---|
[<选择器>] |
由一个或多个选择器组成的子段 |
<选择器> |
子段的快捷方式,由一个独特的选择器组成 |
{"..": [<选择器>]} |
后代段,由一个或多个选择器组成 |
{"..": <选择器>} |
后代段的快捷方式,由一个独特的选择器组成 |
选择器
选择器产生一个包含零个或多个输入值的子节点的节点列表。
语法 | 描述 |
---|---|
<CBOR文本> <CBOR字节> <CBOR整数> <CBOR浮点数> <CBOR布尔值> <CBOR空值> |
键选择器 :根据子键选择 CBOR Map 的子节点 |
{"*": 1} |
通配符选择器 :选择一个节点的所有子节点 |
{"#": <索引> } |
索引选择器 :选择数组的索引子节点(从0开始) |
{":": [<开始>, <结束>, <步长>]} |
数组切片选择器 :选择数组元素的一个子集(在 开始 和 结束 之间,步长为 步长 ) |
{"?": <布尔值-表达式>} |
过滤器选择器 :使用布尔表达式选择特定的子节点 |
布尔表达式
布尔表达式返回 true
或 false
,并由 过滤器选择器
用于过滤数组元素或映射项。
语法 | 描述 |
---|---|
{"&&": [<布尔值-表达式>, <布尔值-表达式>]} |
逻辑 AND |
{"||": [<布尔值-表达式>, <布尔值-表达式>]} |
逻辑 OR |
{"!": <布尔值-表达式>} |
逻辑 NOT |
{"<=": [<可比较的>, <可比较的>]} |
比较 `小于或等于` |
{"<": [<可比较的>, <可比较的>]} |
比较 小于 |
{"==": [<可比较的>, <可比较的>]} |
比较 等于 |
{"!=": [<可比较的>, <可比较的>]} |
比较 不等于 |
{">": [<可比较的>, <可比较的>]} |
比较 大于 |
{">=": [<可比较的>, <可比较的>]} |
比较 大于或等于 |
{"匹配": [<可比较的>, <正则表达式>]} |
匹配函数,用于计算正则表达式的完全匹配。 返回布尔值 |
{"搜索": [<可比较的>, <正则表达式>]} |
长度函数,用于计算正则表达式的子串匹配。 返回布尔值 |
可比较的
一个 可比较的
是一个 过滤器
比较的运算符或函数的参数。
语法 | 描述 |
---|---|
<CBOR文本> <CBOR字节> <CBOR整数> <CBOR浮点数> <CBOR布尔值> <CBOR空值> |
一个 CBOR 值 |
["$", <单数-段>] ["@", <单数-段>] |
一个单数路径(路径产生一个最多包含一个节点的节点列表) |
{"长度": <可比较的>} |
长度函数,用于计算值的长度。 返回一个无符号整数 |
{"计数": <路径>} |
计数函数,用于计算路径中节点的数量。 返回一个无符号整数 |
{"值": <路径>} |
值函数,用于获取单个节点路径的数量。 返回一个 CBOR 值 |
单数段
一个 单数段
产生一个最多包含一个节点的节点列表。
语法 | 描述 |
---|---|
<CBOR文本> <CBOR字节> <CBOR整数> <CBOR浮点数> <CBOR布尔值> <CBOR空值> |
键选择器 :根据子键选择 CBOR Map 的子节点 |
{"#": <索引> } |
索引选择器 :选择数组的索引子节点(从0开始) |
示例
本节为信息性内容。它提供了CBORPath表达式的示例。
这些示例基于表示书店(还有一辆自行车)的简单CBOR值。
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 399
}
}
}
下表显示了可能应用于此示例的一些CBORPath查询及其预期结果。
语法 | 预期结果 |
---|---|
["$", "store", "book", {"*": 1}, "author"] |
书店中所有书的作者 |
["$", {"..": "author"}] |
所有作者 |
["$", "store", {"*": 1}] |
店中的所有东西,其中有一些书 还有一辆红色的自行车 |
["$", "store", {"..": "price"}] |
店中所有物品的价格 |
["$", {"..": "book"}, {"#": 2}] |
第三本书 |
["$", {"..": "book"}, {"#": -1}] |
顺序中的最后一本书 |
["$", {"..": "book"}, [{"#": 0}, {"#": 1}]] 或者 ["$", {"..": "book"}, {":": [0, 2, 1]}] |
前两本书 |
["$", {"..": "book"}, {"?": ["@", "isbn"]}] |
所有带有ISBN编号的书 |
["$", {"..": "book"}, {"?": {"<": [["@", "price"], 10.0]}}] |
所有价格低于10的书 |
["$", {"..": {"*": 1}}] |
所有映射项值和数组元素 包含在输入值中 |
库使用
以下是一些基于上一节示例的代码示例。
use cborpath::{CborPath, builder, Error};
use cbor_diag::parse_diag;
pub fn diag_to_bytes(cbor_diag_str: &str) -> Vec<u8> {
parse_diag(cbor_diag_str).unwrap().to_bytes()
}
fn main() -> Result<(), Error> {
let value = diag_to_bytes(
r#"{
"store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 399
}
}
}"#,
);
// the authors of all books in the store
// ["$", "store", "book", {"*": 1}, "author"]
let cbor_path = CborPath::builder()
.key("store")
.key("book")
.wildcard()
.key("author")
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
]"#
),
results
);
// all authors
// ["$", {"..": "author"}]
let cbor_path = CborPath::builder()
.descendant(builder::segment().key("author"))
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
]"#
),
results
);
// all things in store, which are some books and a red bicycle
// ["$", "store", {"*": 1}]
let cbor_path = CborPath::builder().key("store").wildcard().build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[[
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
{
"color": "red",
"price": 399
}]"#
),
results
);
// the prices of everything in the store
// ["$", "store", {"..": "price"}]
let cbor_path = CborPath::builder()
.key("store")
.descendant(builder::segment().key("price"))
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[
399,
8.95,
12.99,
8.99,
22.99
]"#
),
results
);
// the third book
// ["$", {"..": "book"}, {"#": 2}]
let cbor_path = CborPath::builder()
.descendant(builder::segment().key("book"))
.index(2)
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}]"#
),
results
);
// the last book in order
// ["$", {"..": "book"}, {"#": -1}]
let cbor_path = CborPath::builder()
.descendant(builder::segment().key("book"))
.index(-1)
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}]"#
),
results
);
// the first two books
// ["$", {"..": "book"}, [{"#": 0}, {"#": 1}]]
let cbor_path = CborPath::builder()
.descendant(builder::segment().key("book"))
.child(builder::segment().index(0).index(1))
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}]"#
),
results
);
// the first two books
// ["$", {"..": "book"}, {":": [0, 2, 1]}]
let cbor_path = CborPath::builder()
.descendant(builder::segment().key("book"))
.slice(0, 2, 1)
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}]"#
),
results
);
// all books with an ISBN number
// ["$", {"..": "book"}, {"?": ["@", "isbn"]}]
let cbor_path = CborPath::builder()
.descendant(builder::segment().key("book"))
.filter(builder::rel_path().key("isbn"))
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}]"#
),
results
);
// all books cheaper than 10
// ["$", {"..": "book"}, {"?": {"<": [["@", "price"], 10.0]}}]
let cbor_path = CborPath::builder()
.descendant(builder::segment().key("book"))
.filter(builder::lt(
builder::sing_rel_path().key("price"),
builder::val(10.),
))
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}]"#
),
results
);
// all map item values and array elements contained in input value
// ["$", {"..": {"*": 1}}]
let cbor_path = CborPath::builder()
.descendant(builder::segment().wildcard())
.build();
let results = cbor_path.read_from_bytes(&value)?;
assert_eq!(
diag_to_bytes(
r#"[{
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 399
}
},
[
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
{
"color": "red",
"price": 399
},
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
},
"red",
399,
"reference",
"Nigel Rees",
"Sayings of the Century",
8.95,
"fiction",
"Evelyn Waugh",
"Sword of Honour",
12.99,
"fiction",
"Herman Melville",
"Moby Dick",
"0-553-21311-3",
8.99,
"fiction",
"J. R. R. Tolkien",
"The Lord of the Rings",
"0-395-19395-8",
22.99
]"#
),
results
);
Ok(())
}
依赖
~3–4MB
~72K SLoC