logo

Derive Macro zvariant::Type

source · []
#[derive(Type)]
{
    // Attributes available to this derive:
    #[zvariant]
}
Expand description

Derive macro to add Type implementation to structs and enums.

Examples

For structs it works just like serde’s Serialize and Deserialize macros:

use zvariant::{EncodingContext, from_slice, to_bytes, Type};
use serde::{Deserialize, Serialize};
use byteorder::LE;

#[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 = EncodingContext::<LE>::new_dbus(0);
let encoded = to_bytes(ctxt, &s).unwrap();
let decoded: Struct = from_slice(&encoded, ctxt).unwrap();
assert_eq!(decoded, s);

Same with enum, except that only enums with unit variants are supported. If you want the encoding size of the enum to be dictated by repr attribute (like in the example below), you’ll also need serde_repr crate.

use zvariant::{EncodingContext, from_slice, to_bytes, Type};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use byteorder::LE;

#[repr(u8)]
#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq)]
enum Enum {
    Variant1,
    Variant2,
}
assert_eq!(Enum::signature(), u8::signature());
let ctxt = EncodingContext::<LE>::new_dbus(0);
let encoded = to_bytes(ctxt, &Enum::Variant2).unwrap();
let decoded: Enum = from_slice(&encoded, ctxt).unwrap();
assert_eq!(decoded, Enum::Variant2);

#[repr(i64)]
#[derive(Deserialize_repr, Serialize_repr, Type)]
enum Enum2 {
    Variant1,
    Variant2,
}
assert_eq!(Enum2::signature(), i64::signature());

// w/o repr attribute, u32 representation is chosen
#[derive(Deserialize, Serialize, Type)]
enum NoReprEnum {
    Variant1,
    Variant2,
}
assert_eq!(NoReprEnum::signature(), u32::signature());

Custom signatures

There are times when you’d find yourself wanting to specify a hardcoded signature yourself for the type. The signature attribute exists for this purpose. A typical use case is when you’d need to encode your type as a dictionary (signature a{sv}) type. For convenience, dict is an alias for a{sv}. Here is an example:

use zvariant::{SerializeDict, DeserializeDict, EncodingContext, from_slice, to_bytes, Type};
use byteorder::LE;

#[derive(DeserializeDict, SerializeDict, Type, PartialEq, Debug)]
// `#[zvariant(signature = "a{sv}")]` would be the same.
#[zvariant(signature = "dict")]
struct Struct {
    field1: u16,
    field2: i64,
    field3: String,
}

assert_eq!(Struct::signature(), "a{sv}");
let s = Struct {
    field1: 42,
    field2: i64::max_value(),
    field3: "hello".to_string(),
};
let ctxt = EncodingContext::<LE>::new_dbus(0);
let encoded = to_bytes(ctxt, &s).unwrap();
let decoded: Struct = from_slice(&encoded, ctxt).unwrap();
assert_eq!(decoded, s);