#serialization #serde #cbor #no-std

no-std serde_ipld_dagcbor

IPLD DAG-CBOR support for Serde

13 unstable releases (5 breaking)

0.6.1 Apr 24, 2024
0.6.0 Mar 26, 2024
0.5.0 Mar 18, 2024
0.4.2 Sep 12, 2023
0.1.2 Mar 21, 2022

#99 in Encoding

Download history 4054/week @ 2024-02-01 4330/week @ 2024-02-08 4594/week @ 2024-02-15 3369/week @ 2024-02-22 4510/week @ 2024-02-29 3993/week @ 2024-03-07 4773/week @ 2024-03-14 4002/week @ 2024-03-21 3388/week @ 2024-03-28 3676/week @ 2024-04-04 3856/week @ 2024-04-11 3131/week @ 2024-04-18 2358/week @ 2024-04-25 2329/week @ 2024-05-02 2452/week @ 2024-05-09 2105/week @ 2024-05-16

9,800 downloads per month
Used in 144 crates (19 directly)


1.5K SLoC


Crates.io Documentation

This is a Serde implementation for DAG-CBOR. It can be use in conjunction with ipld-core.

The underlying library for CBOR encoding/decoding is cbor4ii and the Serde implementation is also heavily based on their code.

This crate started as a fork of serde_cbor, thanks everyone involved there.


Storing and loading Rust types is easy and requires only minimal modifications to the program code.

use serde_derive::{Deserialize, Serialize};
use std::error::Error;
use std::fs::File;
use std::io::BufReader;

// Types annotated with `Serialize` can be stored as DAG-CBOR.
// To be able to load them again add `Deserialize`.
#[derive(Debug, Serialize, Deserialize)]
struct Mascot {
    name: String,
    species: String,
    year_of_birth: u32,

fn main() -> Result<(), Box<dyn Error>> {
    let ferris = Mascot {
        name: "Ferris".to_owned(),
        species: "crab".to_owned(),
        year_of_birth: 2015,

    let ferris_file = File::create("examples/ferris.cbor")?;
    // Write Ferris to the given file.
    // Instead of a file you can use any type that implements `io::Write`
    // like a HTTP body, database connection etc.
    serde_ipld_dagcbor::to_writer(ferris_file, &ferris)?;

    let tux_file = File::open("examples/tux.cbor")?;
    let tux_reader = BufReader::new(tux_file);
    // Load Tux from a file.
    // Serde IPLD DAG-CBOR performs roundtrip serialization meaning that
    // the data will not change in any way.
    let tux: Mascot = serde_ipld_dagcbor::from_reader(tux_reader)?;

    println!("{:?}", tux);
    // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }




The codec feature is enabled by default, it 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.


Sometimes it is desired that a CID is not accidentally deserialized into bytes. This can happen because the intermediate serde data model does not retain enough information to be able to differentiate between a bytes container and a CID container when there is a conflicting choice to be made, as in the case of some enum cases. The no-cid-as-bytes feature can be enabled in order to error at runtime in such cases.

The problem with that feature is, that it breaks Serde's derive attributes for internally tagged enums (#[serde(tag = "sometag")]) and untagged enums (#serde(untagged)). If this feature is enabled and you still need similar functionality, you could implement a deserializer manually. Examples of how to do that are in the enum example.


Licensed under either of

at your option.


~55K SLoC