#ipld #traversal #css-selectors #methods

ipld_traversal

IPLD选择器和遍历方法的实现

4个版本

0.2.2 2023年1月7日
0.2.1 2022年12月23日
0.2.0 2022年12月23日
0.1.0 2022年9月13日

#40 in #traversal

25 每月下载次数
graphsync 中使用

MIT 许可证

56KB
1.5K SLoC

此crate提供了一个库,用于构建IPLD选择器和运行GraphSync协议实现的遍历。它试图反映go-ipld-prime实现,尽管它不包含所有功能。

Blockstore

该trait使用了Filecoin FVM实现中使用的trait。它不关心编解码器,与Libipld blockstore架构相反,因为其泛型参数类型要求可能对消费者不友好。

相反,类似于ipld-prime实现的LinkSystem可以将blockstore包装起来,以提供编解码器支持和存储Ipld值的简单接口。

use ipld_traversal::{LinkSystem, blockstore::MemoryBlockstore, Prefix};
use libipld::ipld;

let store = MemoryBlockstore::new();

let link_system = LinkSystem::new(store);

let sample_data = ipld!({
"Size": 100,
});

let cid = link_system.store(Prefix::builder().dag_json().sha256().build(), &sample_data).unwrap();

Selectors

包括实化在内,最常见的选择器功能。

use ipld_traversal::selector::{Selector, RecursionLimit};
use indexmap::indexmap;

let selector = Selector::ExploreRecursive {
limit: RecursionLimit::None,
sequence: Box::new(Selector::ExploreAll {
next: Box::new(Selector::ExploreRecursiveEdge),
}),
current: None,
};

let reified = Selector::ExploreInterpretAs {
reifier: "unixfs".to_string(),
next: Box::new(Selector::ExploreFields {
fields: indexmap! {
"path".to_string() => Selector::Matcher,
},
}),
};

如果不介意从头开始构建一个,可以直接使用

use ipld_traversal::unixfs::unixfs_path_selector;

let (cid, selector) = unixfs_path_selector("bafybeihq3wo4u27amukm36i7vbpirym4y2lvy53uappzhl3oehcm4ukphu/dir/file.ext".into()).unwrap();

Traversal

要运行ipld遍历,提供了一个迭代器接口。请注意,迭代器将遍历由选择器定义的确切树,但仅返回链接解析到的IPLD节点。这与ipld-prime walkAdv回调不同,后者将返回所有中间IPLD节点。

use ipld_traversal::{Selector, LinkSystem, blockstore::MemoryBlockstore, IpldTraversal, Prefix};
use libipld::ipld;

let store = MemoryBlockstore::new();
let lsys = LinkSystem::new(store);

let prefix = Prefix::builder().dag_cbor().sha256().build();
let leaf = ipld!({ "name": "leaf1", "size": 12 });
let root = lsys.store(prefix, &leaf).unwrap();

let selector = Selector::ExploreAll {
next: Box::new(Selector::ExploreRecursiveEdge),
};

let mut it = IpldTraversal::new(lsys, root, selector);

let node = it.next().unwrap().unwrap();
assert_eq!(node, leaf);

块遍历按照给定的选择器遍历IPLD树,同时在沿途返回所有解析的块。

use ipld_traversal::{Selector, LinkSystem, blockstore::MemoryBlockstore, BlockTraversal, Prefix};
use libipld::ipld;

let store = MemoryBlockstore::new();
let lsys = LinkSystem::new(store);

let prefix = Prefix::builder().dag_cbor().sha256().build();
let leaf = ipld!({ "name": "ipld node", "size": 10 });
let (root, bytes) = lsys.store_plus_raw(prefix, &leaf).unwrap();

let selector = Selector::ExploreAll {
next: Box::new(Selector::ExploreRecursiveEdge),
};

let mut it = BlockTraversal::new(lsys, root, selector);

let (cid, block) = it.next().unwrap().unwrap();
assert_eq!(block, bytes);

依赖关系

~5–14MB
~168K SLoC