7 unstable releases (3 breaking)

0.4.1 Mar 28, 2024
0.4.0 Mar 26, 2024
0.3.2 Mar 14, 2024
0.2.0 Feb 23, 2024
0.1.0 Jan 25, 2024

#3 in #links

Download history 25/week @ 2024-03-03 327/week @ 2024-03-10 169/week @ 2024-03-17 518/week @ 2024-03-24 227/week @ 2024-03-31 223/week @ 2024-04-07 210/week @ 2024-04-14 169/week @ 2024-04-21 260/week @ 2024-04-28 356/week @ 2024-05-05 467/week @ 2024-05-12 508/week @ 2024-05-19 223/week @ 2024-05-26 240/week @ 2024-06-02 330/week @ 2024-06-09 501/week @ 2024-06-16

1,321 downloads per month
Used in 12 crates (6 directly)



IPLD core

Crates.io Documentation

This crate provides core types for interoperating with IPLD. Codecs are not part of this crate, they are independent, but rely on ipld-core.

The code is based on libipld-core. The major difference is that Serde is used a lot more for better interoperability with the rest of the Rust ecosystem.


Codec independent code

One of the main features of IPLD is that your Codec is independent of the data you are encoding. Hence it's common that you want to have your code to be independent of a specific code, but rather be generic.

Here's a full example of a function that can encode data with both serde_ipld_dagcbor or serde_ipld_dagjson:

use std::str;

use ipld_core::codec::Codec;
use serde::{Deserialize, Serialize};
use serde_ipld_dagcbor::codec::DagCborCodec;
use serde_ipld_dagjson::codec::DagJsonCodec;

#[derive(Deserialize, Serialize)]
struct Tree {
    height: u8,
    age: u8,

fn encode_generic<C, T>(value: &T) -> Result<Vec<u8>, C::Error>
    C: Codec<T>,

fn main() {
    let tree = Tree {
        height: 12,
        age: 91,

    let cbor_encoded = encode_generic::<DagCborCodec, _>(&tree);
    let cbor_hex = cbor_encoded
        .map(|byte| format!("{:02x}", byte))
    // CBOR encoded: https://cbor.nemo157.com/#value=a2666865696768740c63616765185b
    println!("CBOR encoded: https://cbor.nemo157.com/#value={}", cbor_hex);
    let json_encoded = encode_generic::<DagJsonCodec, _>(&tree).unwrap();
    // JSON encoded: {"height":12,"age":91}
    println!("JSON encoded: {}", str::from_utf8(&json_encoded).unwrap());

If you are only interested in the links (CIDs) of an encoded IPLD object, then you can extract them them directly with [Codec::links()]:

use ipld_core::{codec::{Codec, Links}, ipld, cid::Cid};
use serde_ipld_dagjson::codec::DagJsonCodec;

fn main() {
    let cid = Cid::try_from("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap();
    let data = ipld!({"some": {"nested": cid}, "or": [cid, cid], "more": true});

    let mut encoded = Vec::new();
    DagJsonCodec::encode(&mut encoded, &data).unwrap();

    let links = DagJsonCodec::links(&encoded).unwrap().collect::<Vec<_>>();
    // Extracted links: [Cid(bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy), Cid(bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy), Cid(bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy)]
    println!("Extracted links: {:?}", links);

Feature flags

  • std (enabled by default): Makes the error implement std::error::Error and the Codec trait available.
  • codec (enabled by default): Provides the Codec trait, which enables encoding and decoding independent of the IPLD Codec. The minimum supported Rust version (MSRV) can significantly be reduced to 1.64 by disabling this feature.
  • serde: Enables support for Serde serialization into/deserialization from the Ipld enum.
  • arb: Enables support for property based testing.


Licensed under either of

at your option.


~50K SLoC