Crate zvariant

Source
Expand description

§zvariant

This crate provides API for encoding/decoding of data to/from D-Bus wire format. This binary wire format is simple and very efficient and hence useful outside of D-Bus context as well. A modified form of this format, GVariant is very commonly used for efficient storage of arbitrary data and is also supported by this crate (if you enable gvariant cargo feature).

Since version 2.0, the API is serde-based and hence you’ll find it very intuitive if you’re already familiar with serde. If you’re not familiar with serde, you may want to first read its tutorial before learning further about this crate.

Status: Stable.

§Example code

Serialization and deserialization is achieved through the toplevel functions:

use std::collections::HashMap;
use zvariant::{serialized::Context, to_bytes, Type, LE};
use serde::{Deserialize, Serialize};

// All serialization and deserialization API, needs a context.
let ctxt = Context::new_dbus(LE, 0);
// You can also use the more efficient GVariant format:
// let ctxt = Context::new_gvariant(LE, 0);

// i16
let encoded = to_bytes(ctxt, &42i16).unwrap();
let decoded: i16 = encoded.deserialize().unwrap().0;
assert_eq!(decoded, 42);

// strings
let encoded = to_bytes(ctxt, &"hello").unwrap();
let decoded: &str = encoded.deserialize().unwrap().0;
assert_eq!(decoded, "hello");

// tuples
let t = ("hello", 42i32, true);
let encoded = to_bytes(ctxt, &t).unwrap();
let decoded: (&str, i32, bool) = encoded.deserialize().unwrap().0;
assert_eq!(decoded, t);

// Vec
let v = vec!["hello", "world!"];
let encoded = to_bytes(ctxt, &v).unwrap();
let decoded: Vec<&str> = encoded.deserialize().unwrap().0;
assert_eq!(decoded, v);

// Dictionary
let mut map: HashMap<i64, &str> = HashMap::new();
map.insert(1, "123");
map.insert(2, "456");
let encoded = to_bytes(ctxt, &map).unwrap();
let decoded: HashMap<i64, &str> = encoded.deserialize().unwrap().0;
assert_eq!(decoded[&1], "123");
assert_eq!(decoded[&2], "456");

// derive macros to handle custom types.
#[derive(Deserialize, Serialize, Type, PartialEq, Debug)]
struct Struct<'s> {
    field1: u16,
    field2: i64,
    field3: &'s str,
}

assert_eq!(Struct::SIGNATURE, "(qxs)");
let s = Struct {
    field1: 42,
    field2: i64::max_value(),
    field3: "hello",
};
let ctxt = Context::new_dbus(LE, 0);
let encoded = to_bytes(ctxt, &s).unwrap();
let decoded: Struct = encoded.deserialize().unwrap().0;
assert_eq!(decoded, s);

// It can handle enums too, just that all variants must have the same number and types of fields.
// Names of fields don't matter though. You can make use of `Value` or `OwnedValue` if you want to
// encode different data in different fields.
#[derive(Deserialize, Serialize, Type, PartialEq, Debug)]
enum Enum<'s> {
    Variant1 { field1: u16, field2: i64, field3: &'s str },
    Variant2(u16, i64, &'s str),
    Variant3 { f1: u16, f2: i64, f3: &'s str },
}

// Enum encoding uses a `u32` to denote the variant index. For unit-type enums that's all that's
// needed so the signature is just `u` but complex enums are encoded as a structure whose first
// field is the variant index and the second one is the field(s).
assert_eq!(Enum::SIGNATURE, "(u(qxs))");
let e = Enum::Variant3 {
    f1: 42,
    f2: i64::max_value(),
    f3: "hello",
};
let encoded = to_bytes(ctxt, &e).unwrap();
let decoded: Enum = encoded.deserialize().unwrap().0;
assert_eq!(decoded, e);

// Enum encoding can be adjusted by using the `serde_repr` crate
// and by annotating the representation of the enum with `repr`.
use serde_repr::{Serialize_repr, Deserialize_repr};

#[derive(Deserialize_repr, Serialize_repr, Type, PartialEq, Debug)]
#[repr(u8)]
enum UnitEnum {
    Variant1,
    Variant2,
    Variant3,
}

assert_eq!(UnitEnum::SIGNATURE, "y");
let encoded = to_bytes(ctxt, &UnitEnum::Variant2).unwrap();
let e: UnitEnum = encoded.deserialize().unwrap().0;
assert_eq!(e, UnitEnum::Variant2);

// Unit enums can also be (de)serialized as strings.
#[derive(Deserialize, Serialize, Type, PartialEq, Debug)]
#[zvariant(signature = "s")]
enum StrEnum {
    Variant1,
    Variant2,
    Variant3,
}

assert_eq!(StrEnum::SIGNATURE, "s");

Apart from the obvious requirement of serialized::Context instance by the main serialization and deserialization API, the type being serialized or deserialized must also implement Type trait in addition to Serialize or Deserialize, respectively. Please refer to Type module documentation for more details.

Most of the basic types of D-Bus match 1-1 with all the primitive Rust types. The only two exceptions being, Signature and ObjectPath, which are really just strings. These types are covered by the Basic trait.

Similarly, most of the container types also map nicely to the usual Rust types and collections (as can be seen in the example code above). The only note worthy exception being ARRAY type. As arrays in Rust are fixed-sized, serde treats them as tuples and so does this crate. This means they are encoded as STRUCT type of D-Bus. If you need to serialize to, or deserialize from a D-Bus array, you’ll need to use a slice (array can easily be converted to a slice), a Vec or an arrayvec::ArrayVec.

D-Bus string types, including Signature and ObjectPath, require one additional restriction that strings in Rust do not. They must not contain any interior null bytes ('\0'). Encoding/Decoding strings that contain this character will return an error.

The generic D-Bus type, VARIANT is represented by Value, an enum that holds exactly one value of any of the other types. Please refer to Value module documentation for examples.

§no-std

While std is currently a hard requirement, optional no-std support is planned in the future. On the other hand, noalloc support is not planned as it will be extremely difficult to accomplish. However, community contribution can change that. 😊

§Optional features

FeatureDescription
gvariantEnable GVariant format support
arrayvecImplement Type for arrayvec::ArrayVec and arrayvec::ArrayString
enumflags2Implement Type for enumflags2::BitFlags<F>
option-as-arrayEnable Option<T> (de)serialization using array encoding

gvariant features conflicts with option-as-array and hence should not be enabled together.

Modules§

dbus
gvariant
serialized
signature

Macros§

impl_type_with_repr
Implements the Type trait by delegating the signature to a simpler type (usually a tuple). Tests that ensure that the two types are serialize-compatible are auto-generated.
static_str_type

Structs§

Array
A helper type to wrap arrays in a Value.
ArraySeed
Use this to deserialize an Array.
DeserializeValue
A wrapper to deserialize a value to T: Type + Deserialize.
Dict
A helper type to wrap dictionaries in a Value.
DynamicTuple
A helper type to serialize or deserialize a tuple whose elements implement DynamicType but not Type.
Maybe
A helper type to wrap Option<T> (GVariant’s Maybe type) in Value.
ObjectPath
String that identifies objects at a given destination on the D-Bus bus.
Optional
An optional value.
OwnedFd
A file-descriptor type wrapper.
OwnedObjectPath
Owned ObjectPath
OwnedStructure
Owned Structure
OwnedStructureSeed
Use this to deserialize an OwnedStructure.
OwnedValue
Owned Value
SerializeValue
A wrapper to serialize T: Type + Serialize as a value.
Str
A string wrapper.
Structure
A helper type to wrap structs in Value.
StructureBuilder
Use this to efficiently build a Structure.
StructureSeed
Use this to deserialize a Structure.
TupleSeed
A helper type for DynamicTuple’s DynamicDeserialize implementation.

Enums§

Endian
The endian of the data.
Error
Error type used by zvariant API.
Fd
A file-descriptor type wrapper.
MaxDepthExceeded
Enum representing the max depth exceeded error.
Signature
A D-Bus signature in parsed form.
Value
A generic container, in the form of an enum that holds exactly one value of any of the other types.

Constants§

ARRAY_SIGNATURE_CHAR
The prefix of ARRAY type signature, as a character. Provided for manual signature creation.
ARRAY_SIGNATURE_STR
The prefix of ARRAY type signature, as a string. Provided for manual signature creation.
BE
Alias for Endian::Big.
DICT_ENTRY_SIG_END_CHAR
The closing character of DICT_ENTRY type signature. Provided for manual signature creation.
DICT_ENTRY_SIG_END_STR
The closing character of DICT_ENTRY type signature, as a string. Provided for manual signature creation.
DICT_ENTRY_SIG_START_CHAR
The opening character of DICT_ENTRY type signature. Provided for manual signature creation.
DICT_ENTRY_SIG_START_STR
The opening character of DICT_ENTRY type signature, as a string. Provided for manual signature creation.
LE
Alias for Endian::Little.
MAYBE_SIGNATURE_CHAR
The prefix of MAYBE (GVariant-specific) type signature, as a character. Provided for manual signature creation.
MAYBE_SIGNATURE_STR
The prefix of MAYBE (GVariant-specific) type signature, as a string. Provided for manual signature creation.
NATIVE_ENDIAN
Same as the return value of Endian::native.
NETWORK_ENDIAN
Alias for Endian::Big.
STRUCT_SIG_END_CHAR
The closing character of STRUCT type signature. Provided for manual signature creation.
STRUCT_SIG_END_STR
The closing character of STRUCT type signature, as a string. Provided for manual signature creation.
STRUCT_SIG_START_CHAR
The opening character of STRUCT type signature. Provided for manual signature creation.
STRUCT_SIG_START_STR
The opening character of STRUCT type signature, as a string. Provided for manual signature creation.
VARIANT_SIGNATURE_CHAR
The VARIANT type signature. Provided for manual signature creation.
VARIANT_SIGNATURE_STR
The VARIANT type signature, as a string. Provided for manual signature creation.

Traits§

Basic
Trait for basic types.
DynamicDeserialize
Types that deserialize based on dynamic signatures.
DynamicType
Types with dynamic signatures.
NoneValue
Type that uses a special value to be used as none.
ReadBytes
A trait for reading bytes.
Type
Trait implemented by all serializable types.
WriteBytes
A trait for writing bytes.

Functions§

serialized_size
Calculate the serialized size of T.
to_bytes
Serialize T as a byte vector.
to_bytes_for_signature
Serialize T that has the given signature, to a new byte vector.
to_writer
Serialize T to the given writer.
to_writer_for_signature
Serialize T that has the given signature, to the given writer.

Type Aliases§

Result
Alias for a Result with the error type zvariant::Error.

Derive Macros§

DeserializeDict
Adds Deserialize implementation to structs to be deserialized from a{sv} type.
OwnedValue
Implements conversions for your type to/from OwnedValue.
SerializeDict
Adds Serialize implementation to structs to be serialized as a{sv} type.
Type
Derive macro to add Type implementation to structs and enums.
Value
Implements conversions for your type to/from Value.