Crate ipld_traversal

Source
Expand description

This crate provides a library for constructing IPLD selectors and running traversals for the GraphSync protocol implementation. It tries to mirror go-ipld-prime implementation although it does not contain all the features.

§Blockstore

The trait copies one used by the Filecoin FVM implementation. It does not worry about codecs contrary to the Libipld blockstore architecture which can be unfriendly to consumers because of the generic parameter types requirements.

Instead, a LinkSystem akin to the ipld-prime implementation can wrap the blockstore to provide codec support and a simplement interface for storing Ipld values directly.

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

Most commonly used selector features including reification.

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,
        },
    }),
};

Or not to bother with constructing one from scratch one can simply use:

use ipld_traversal::unixfs::unixfs_path_selector;

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

§Traversal

To run an ipld traversal, an iterator interface is available. Note that the iterator will traverse the exact tree as defined by the selector but only return the IPLD node the links resolve to. This is different from say the ipld-prime walkAdv callback which will return every intermediary ipld nodes.

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);

A block traversal walks the IPLD tree as defined by a given selector while returning all the blocks resolved along the way.

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);

Re-exports§

pub use link_system::BlockLoader;
pub use link_system::IpldLoader;
pub use link_system::LinkSystem;
pub use link_system::LoaderError;
pub use link_system::Prefix;
pub use selector::Selector;

Modules§

blockstore
link_system
path_segment
selector
unixfs

Structs§

BlockIter
BlockTraversal
Executes an iterative traversal based on the given root CID and selector and returns the blocks resolved along the way.
IpldTraversal
Executes an iterative traversal based on the given root CID and selector and returns the decoded IPLD nodes resolved along the way.
SelectIpldIter
TraversalValidator

Enums§

IterError