#no-std #serialization

no-std musli-storage

Partially upgrade stable format for Müsli suitable for storage

49 releases

0.0.49 May 18, 2023
0.0.48 May 18, 2023
0.0.39 Apr 26, 2023
0.0.38 Mar 22, 2023
0.0.29 Apr 30, 2022

#294 in Encoding

Download history 41/week @ 2023-02-07 116/week @ 2023-02-14 78/week @ 2023-02-21 8/week @ 2023-02-28 7/week @ 2023-03-07 9/week @ 2023-03-14 108/week @ 2023-03-21 9/week @ 2023-03-28 2/week @ 2023-04-04 48/week @ 2023-04-11 1/week @ 2023-04-18 36/week @ 2023-04-25 25/week @ 2023-05-02 222/week @ 2023-05-09 305/week @ 2023-05-16 75/week @ 2023-05-23

628 downloads per month
Used in 6 crates (4 directly)

MIT/Apache

320KB
6K SLoC

musli-storage

github crates.io docs.rs build status

Super simple storage encoding for Müsli

The storage encoding is partially upgrade safe:

  • ✔ Can tolerate missing fields if they are annotated with #[musli(default)].
  • ✗ Cannot skip over extra unrecognized fields.

This means that it's suitable as a storage format, since the data model only evolves in one place. But unsuitable as a wire format since it cannot allow clients to upgrade independent of each other.

See musli-wire for a fully upgrade safe format.

use musli::{Encode, Decode};

#[derive(Debug, PartialEq, Encode, Decode)]
struct Version1 {
    name: String,
}

#[derive(Debug, PartialEq, Encode, Decode)]
struct Version2 {
    name: String,
    #[musli(default)]
    age: Option<u32>,
}

let version2 = musli_storage::to_buffer(&Version2 {
    name: String::from("Aristotle"),
    age: Some(62),
})?;

assert!(musli_storage::decode::<_, Version1>(version2.as_slice()).is_err());

let version1 = musli_storage::to_buffer(&Version1 {
    name: String::from("Aristotle"),
})?;

let version2: Version2 = musli_storage::decode(version1.as_slice())?;

assert_eq!(version2, Version2 {
    name: String::from("Aristotle"),
    age: None,
});

Configuring

To tweak the behavior of the storage format you can use the Encoding type:

use musli_storage::Encoding;
use musli_storage::int::{Fixed, Variable};
use musli::mode::DefaultMode;
use musli::{Encode, Decode};

const CONFIG: Encoding<DefaultMode, Fixed, Variable> = Encoding::new()
    .with_fixed_integers();

#[derive(Debug, PartialEq, Encode, Decode)]
struct Struct<'a> {
    name: &'a str,
    age: u32,
}

let mut out = Vec::new();

let expected = Struct {
    name: "Aristotle",
    age: 61,
};

CONFIG.encode(&mut out, &expected)?;
let actual = CONFIG.decode(&out[..])?;

assert_eq!(expected, actual);

Dependencies

~0.5–1MB
~22K SLoC