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