47 个稳定版本 (3 个主要版本)
4.2.0 | 2024年7月19日 |
---|---|
4.1.1 | 2024年5月20日 |
4.0.2 | 2024年2月25日 |
3.15.2 | 2024年2月25日 |
1.0.2 | 2019年12月30日 |
#143 in 编码
667,985 每月下载量
用于 454 个crate (40 个直接使用)
445KB
11K SLoC
zvariant
此crate提供了数据编码/解码的API,用于从/到D-Bus线格式。这种二进制线格式简单且非常高效,因此在D-Bus上下文之外也很有用。这种格式的修改版,GVariant,被广泛用于高效存储任意数据,并由本crate支持(如果您启用了gvariant
cargo功能)。
自2.0版本以来,API基于serde,因此如果您已经熟悉serde,您会发现它非常直观。如果您不熟悉serde,在学习此crate之前,您可能想先阅读它的教程。
状态:稳定。
示例代码
序列化和反序列化是通过顶级函数实现的
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");
除了主序列化和反序列化API需要显式调用serialized::Context
实例之外,被序列化或反序列化的类型还必须实现Type
trait,以及分别实现Serialize
或Deserialize
。有关更多详细信息,请参阅Type
模块文档。
大多数D-Bus的基本类型与所有原始Rust类型一一对应。唯一的两个例外是,Signature
和ObjectPath
,它们实际上只是字符串。这些类型由Basic
trait处理。
同样,大多数的容器类型也很好地映射到常见的Rust类型和集合(如上述示例代码所示)。唯一值得注意的例外是ARRAY类型。由于Rust中的数组是固定大小的,serde将其视为元组,因此本库也是如此。这意味着它们被编码为D-Bus的STRUCT类型。如果您需要将数据序列化到D-Bus数组或从D-Bus数组反序列化,则需要使用切片(数组可以轻松转换为切片)、Vec
或arrayvec::ArrayVec
。
D-Bus字符串类型,包括Signature
和ObjectPath
,有一个额外的限制,即Rust中的字符串没有。它们不能包含任何内部空字节('\0'
)。包含此字符的字符串的编码/解码将返回错误。
通用的D-Bus类型VARIANT
由Value
表示,这是一个枚举,它恰好包含其他类型的任意一个值。请参阅Value
模块文档以获取示例。
no-std
虽然std
目前是硬性要求,但计划在未来提供可选的no-std
支持。另一方面,noalloc
支持目前没有计划,因为这将非常困难。然而,社区贡献可以改变这一点。😊
可选功能
功能 | 描述 |
---|---|
gvariant | 启用GVariant格式支持 |
arrayvec | 为arrayvec::ArrayVec 和arrayvec::ArrayString 实现Type |
enumflags2 | 为enumflags2::BitFlags <F> 实现Type |
option-as-array | 启用使用数组编码对Option<T> (反)序列化 |
gvariant
功能与option-as-array
冲突,因此不应同时启用。
依赖关系
~1.5–3MB
~65K SLoC