#serialization-format #glib #deserialize #deserialization

no-std gvariant

A pure-rust implementation of the GVariant serialisation format

5 releases (breaking)

0.5.0 May 10, 2022
0.4.0 Sep 14, 2020
0.3.0 Jul 23, 2020
0.2.0 Jun 1, 2020
0.1.0 May 29, 2020

#1621 in Encoding

Download history 634/week @ 2023-11-24 476/week @ 2023-12-01 409/week @ 2023-12-08 373/week @ 2023-12-15 155/week @ 2023-12-22 344/week @ 2023-12-29 445/week @ 2024-01-05 371/week @ 2024-01-12 411/week @ 2024-01-19 560/week @ 2024-01-26 411/week @ 2024-02-02 477/week @ 2024-02-09 270/week @ 2024-02-16 406/week @ 2024-02-23 508/week @ 2024-03-01 291/week @ 2024-03-08

1,548 downloads per month
Used in ostree-ext

MIT/Apache

135KB
2K SLoC

GVariant-rs

A pure-rust implementation of the GVariant serialisation format intended for fast reading of in-memory buffers.

    let string = gv!("s").from_bytes("It works!\0");
    assert_eq!(string, "It works!");

Documentation

Module documentation with examples.

Usage

Add this to your Cargo.toml:

[dependencies]
gvariant = "0.5"

Example: read an ostree dirtree file and print the listing:

use gvariant::{gv, Marker, Structure};
use std::error::Error;

fn ostree_ls(filename: &std::path::Path) -> Result<(), Box<dyn Error>> {
    // Read the data into the buffer and interpret as an OSTree tree:
    let tree = gv!("(a(say)a(sayay))").deserialize(std::fs::File::open(filename)?)?;

    // (a(say)a(sayay)) is a structure, so tree implements gvariant::Structure,
    // and we can turn it into a tuple:
    let (files, dirs) = tree.to_tuple();

    // Print the contents
    for s in dirs {
        let (filename, tree_checksum, meta_checksum) = s.to_tuple();
        println!(
            "{} {} {}/",
            hex::encode(tree_checksum),
            hex::encode(meta_checksum),
            filename
        )
    }

    for f in files {
        let (filename, checksum) = f.to_tuple();
        println!("{} {}", hex::encode(checksum), filename)
    }
    Ok(())
}

Status

  • Support for all GVariant types is implemented
  • Behaviour is identical to GLib's implementation for all data in "normal form". This has been confirmed with fuzz testing. There are some differences for data not in normal form. See https://gitlab.gnome.org/GNOME/glib/-/issues/2121 for more information.

TODO

  • Publish version 1.0
  • Benchmarking and performance improvements
  • Ensure that deserialisation of non-normal structures matches GLib in all cases.

Hacking

Build with:

cargo build

Run tests:

cargo test

Clippy linting:

cargo clippy

Fuzz testing:

RUSTFLAGS='-C overflow-checks=on' ASAN_OPTIONS="detect_leaks=0" cargo +nightly fuzz run --release fuzz_target_1

License

This project is licensed under either of

at your option.

Dependencies

~0.5–1MB
~22K SLoC