#[derive(Type)]
{
// Attributes available to this derive:
#[zbus]
#[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::{serialized::Context, to_bytes, Type, LE};
use serde::{Deserialize, Serialize};
#[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);
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::{serialized::Context, to_bytes, Type, LE};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
#[repr(u8)]
#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq)]
enum Enum {
Variant1,
Variant2,
}
assert_eq!(Enum::SIGNATURE, u8::SIGNATURE);
let ctxt = Context::new_dbus(LE, 0);
let encoded = to_bytes(ctxt, &Enum::Variant2).unwrap();
let decoded: Enum = encoded.deserialize().unwrap().0;
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, serialized::Context, to_bytes, Type, 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 = Context::new_dbus(LE, 0);
let encoded = to_bytes(ctxt, &s).unwrap();
let decoded: Struct = encoded.deserialize().unwrap().0;
assert_eq!(decoded, s);
Another common use for custom signatures is (de)serialization of unit enums as strings:
use zvariant::{serialized::Context, to_bytes, Type, LE};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Type, PartialEq, Debug)]
#[zvariant(signature = "s")]
enum StrEnum {
Variant1,
Variant2,
Variant3,
}
assert_eq!(StrEnum::SIGNATURE, "s");
let ctxt = Context::new_dbus(LE, 0);
let encoded = to_bytes(ctxt, &StrEnum::Variant2).unwrap();
assert_eq!(encoded.len(), 13);
let decoded: StrEnum = encoded.deserialize().unwrap().0;
assert_eq!(decoded, StrEnum::Variant2);