#[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 all variants of the enum must have the same number and types of
fields (if any). If you want the encoding size of the (unit-type) 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());
// Not-unit enums are represented as a structure, with the first field being a u32 denoting the
// variant and the second as the actual value.
#[derive(Deserialize, Serialize, Type)]
enum NewType {
Variant1(f64),
Variant2(f64),
}
assert_eq!(NewType::signature(), "(ud)");
#[derive(Deserialize, Serialize, Type)]
enum StructFields {
Variant1(u16, i64, &'static str),
Variant2 { field1: u16, field2: i64, field3: &'static str },
}
assert_eq!(StructFields::signature(), "(u(qxs))");
§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);
Another common use for custom signatures is (de)serialization of unit enums as strings:
use zvariant::{EncodingContext, from_slice, to_bytes, Type};
use serde::{Deserialize, Serialize};
use byteorder::LE;
#[derive(Deserialize, Serialize, Type, PartialEq, Debug)]
#[zvariant(signature = "s")]
enum StrEnum {
Variant1,
Variant2,
Variant3,
}
assert_eq!(StrEnum::signature(), "s");
let ctxt = EncodingContext::<LE>::new_dbus(0);
let encoded = to_bytes(ctxt, &StrEnum::Variant2).unwrap();
assert_eq!(encoded.len(), 13);
let decoded: StrEnum = from_slice(&encoded, ctxt).unwrap();
assert_eq!(decoded, StrEnum::Variant2);