1# zvariant 2 3[![](https://docs.rs/zvariant/badge.svg)](https://docs.rs/zvariant/) [![](https://img.shields.io/crates/v/zvariant)](https://crates.io/crates/zvariant) 4 5This crate provides API for encoding/decoding of data to/from [D-Bus wire format][dwf]. This binary 6wire format is simple and very efficient and hence useful outside of D-Bus context as well. A 7modified form of this format, [GVariant] is very commonly used for efficient storage of arbitrary 8data and is also supported by this crate. 9 10Since version 2.0, the API is [serde]-based and hence you'll find it very intuitive if you're 11already familiar with serde. If you're not familiar with serde, you may want to first read its 12[tutorial] before learning further about this crate. 13 14**Status:** Stable. 15 16## Example code 17 18Serialization and deserialization is achieved through the [toplevel functions]: 19 20```rust 21use std::collections::HashMap; 22use zvariant::{EncodingContext as Context, from_slice, to_bytes, Type}; 23use serde::{Deserialize, Serialize}; 24use byteorder::LE; 25 26// All serialization and deserialization API, needs a context. 27let ctxt = Context::<LE>::new_dbus(0); 28// You can also use the more efficient GVariant format: 29// let ctxt = Context::<LE>::new_gvariant(0); 30 31// i16 32let encoded = to_bytes(ctxt, &42i16).unwrap(); 33let decoded: i16 = from_slice(&encoded, ctxt).unwrap(); 34assert_eq!(decoded, 42); 35 36// strings 37let encoded = to_bytes(ctxt, &"hello").unwrap(); 38let decoded: &str = from_slice(&encoded, ctxt).unwrap(); 39assert_eq!(decoded, "hello"); 40 41// tuples 42let t = ("hello", 42i32, true); 43let encoded = to_bytes(ctxt, &t).unwrap(); 44let decoded: (&str, i32, bool) = from_slice(&encoded, ctxt).unwrap(); 45assert_eq!(decoded, t); 46 47// Vec 48let v = vec!["hello", "world!"]; 49let encoded = to_bytes(ctxt, &v).unwrap(); 50let decoded: Vec<&str> = from_slice(&encoded, ctxt).unwrap(); 51assert_eq!(decoded, v); 52 53// Dictionary 54let mut map: HashMap<i64, &str> = HashMap::new(); 55map.insert(1, "123"); 56map.insert(2, "456"); 57let encoded = to_bytes(ctxt, &map).unwrap(); 58let decoded: HashMap<i64, &str> = from_slice(&encoded, ctxt).unwrap(); 59assert_eq!(decoded[&1], "123"); 60assert_eq!(decoded[&2], "456"); 61 62// derive macros to handle custom types. 63#[derive(Deserialize, Serialize, Type, PartialEq, Debug)] 64struct Struct<'s> { 65 field1: u16, 66 field2: i64, 67 field3: &'s str, 68} 69 70assert_eq!(Struct::signature(), "(qxs)"); 71let s = Struct { 72 field1: 42, 73 field2: i64::max_value(), 74 field3: "hello", 75}; 76let ctxt = Context::<LE>::new_dbus(0); 77let encoded = to_bytes(ctxt, &s).unwrap(); 78let decoded: Struct = from_slice(&encoded, ctxt).unwrap(); 79assert_eq!(decoded, s); 80``` 81 82Apart from the obvious requirement of [`EncodingContext`] instance by the main serialization and 83deserialization API, the type being serialized or deserialized must also implement `Type` 84trait in addition to [`Serialize`] or [`Deserialize`], respectively. Please refer to [`Type` 85module documentation] for more details. 86 87Most of the [basic types] of D-Bus match 1-1 with all the primitive Rust types. The only two 88exceptions being, [`Signature`] and [`ObjectPath`], which are really just strings. These types 89are covered by the [`Basic`] trait. 90 91Similarly, most of the [container types] also map nicely to the usual Rust types and 92collections (as can be seen in the example code above). The only note worthy exception being 93ARRAY type. As arrays in Rust are fixed-sized, serde treats them as tuples and so does this 94crate. This means they are encoded as STRUCT type of D-Bus. If you need to serialize to, or 95deserialize from a D-Bus array, you'll need to use a [slice] (array can easily be converted to a 96slice), a [`Vec`] or an [`arrayvec::ArrayVec`]. 97 98D-Bus string types, including [`Signature`] and [`ObjectPath`], require one additional 99restriction that strings in Rust do not. They must not contain any interior null bytes (`'\0'`). 100Encoding/Decoding strings that contain this character will return an error. 101 102The generic D-Bus type, `VARIANT` is represented by `Value`, an enum that holds exactly one 103value of any of the other types. Please refer to [`Value` module documentation] for examples. 104 105## no-std 106 107While `std` is currently a hard requirement, optional `no-std` support is planned in the future. 108On the other hand, `noalloc` support is not planned as it will be extremely difficult to 109accomplish. However, community contribution can change that. 110 111## Optional features 112 113| Feature | Description | 114| --- | ----------- | 115| arrayvec | Implement `Type` for [`arrayvec::ArrayVec`] and [`arrayvec::ArrayString`] | 116| enumflags2 | Implement `Type` for [`struct@enumflags2::BitFlags<F>`] | 117 118[dwf]: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling 119[GVariant]: https://people.gnome.org/~desrt/gvariant-serialisation.pdf 120[serde]: https://crates.io/crates/serde 121[tutorial]: https://serde.rs/ 122[toplevel functions]: https://docs.rs/zvariant/latest/zvariant/#functions 123[`EncodingContext`]: https://docs.rs/zvariant/latest/zvariant/struct.EncodingContext.html 124[`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html 125[`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html 126[`Type` module documentation]: https://docs.rs/zvariant/latest/zvariant/trait.Type.html 127[basic types]: https://dbus.freedesktop.org/doc/dbus-specification.html#basic-types 128[`Signature`]: https://docs.rs/zvariant/latest/zvariant/struct.Signature.html 129[`ObjectPath`]: https://docs.rs/zvariant/latest/zvariant/struct.ObjectPath.html 130[`Basic`]: https://docs.rs/zvariant/latest/zvariant/trait.Basic.html 131[container types]: https://dbus.freedesktop.org/doc/dbus-specification.html#container-types 132[slice]: https://doc.rust-lang.org/std/primitive.slice.html 133[`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 134[`arrayvec::ArrayVec`]: https://docs.rs/arrayvec/0.7.1/arrayvec/struct.ArrayVec.html 135[`arrayvec::ArrayString`]: https://docs.rs/arrayvec/0.7.1/arrayvec/struct.ArrayString.html 136[`Value` module documentation]: https://docs.rs/zvariant/latest/zvariant/enum.Value.html 137