tokio_dbus/variant.rs
1use crate::signature::SignatureBuilder;
2use crate::{ObjectPath, Signature, Storable, WriteAligned};
3
4/// A variant holding a value of a basic D-Bus type.
5///
6/// A variant is a value which is prefixed by the [`Signature`] of the value it
7/// contains, which allows a container to hold values of a type which is not
8/// known ahead of time.
9///
10/// Containers inside of a variant cannot be represented by this type. To write
11/// one use [`BodyBuf::store_variant`], and to read one use
12/// [`Body::skip_variant`] to skip over it.
13///
14/// [`BodyBuf::store_variant`]: crate::BodyBuf::store_variant
15/// [`Body::skip_variant`]: crate::Body::skip_variant
16///
17/// # Examples
18///
19/// ```
20/// use tokio_dbus::{BodyBuf, Variant};
21///
22/// let mut body = BodyBuf::new();
23///
24/// body.store(Variant::String("Hello World!"))?;
25/// body.store(Variant::Bool(true))?;
26///
27/// assert_eq!(body.signature(), "vv");
28///
29/// let mut body = body.as_body();
30/// assert!(matches!(body.read_variant()?, Variant::String("Hello World!")));
31/// assert!(matches!(body.read_variant()?, Variant::Bool(true)));
32/// # Ok::<_, tokio_dbus::Error>(())
33/// ```
34#[derive(Debug, Clone, Copy, PartialEq)]
35#[non_exhaustive]
36pub enum Variant<'de> {
37 /// A boolean variant.
38 Bool(bool),
39 /// A single byte variant.
40 U8(u8),
41 /// A signed 16-bit variant.
42 I16(i16),
43 /// An unsigned 16-bit variant.
44 U16(u16),
45 /// A signed 32-bit variant.
46 I32(i32),
47 /// An unsigned 32-bit variant.
48 U32(u32),
49 /// A signed 64-bit variant.
50 I64(i64),
51 /// An unsigned 64-bit variant.
52 U64(u64),
53 /// A 64-bit floating point variant.
54 F64(f64),
55 /// A string variant.
56 String(&'de str),
57 /// An object path variant.
58 ObjectPath(&'de ObjectPath),
59 /// A stored signature.
60 Signature(&'de Signature),
61}
62
63impl Variant<'_> {
64 /// The signature of the value contained in this variant.
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// use tokio_dbus::{Signature, Variant};
70 ///
71 /// assert_eq!(Variant::Bool(true).contained_signature(), Signature::BOOLEAN);
72 /// assert_eq!(Variant::String("hi").contained_signature(), Signature::STRING);
73 /// ```
74 pub fn contained_signature(&self) -> &'static Signature {
75 match self {
76 Variant::Bool(..) => Signature::BOOLEAN,
77 Variant::U8(..) => Signature::BYTE,
78 Variant::I16(..) => Signature::INT16,
79 Variant::U16(..) => Signature::UINT16,
80 Variant::I32(..) => Signature::INT32,
81 Variant::U32(..) => Signature::UINT32,
82 Variant::I64(..) => Signature::INT64,
83 Variant::U64(..) => Signature::UINT64,
84 Variant::F64(..) => Signature::DOUBLE,
85 Variant::String(..) => Signature::STRING,
86 Variant::ObjectPath(..) => Signature::OBJECT_PATH,
87 Variant::Signature(..) => Signature::SIGNATURE,
88 }
89 }
90}
91
92impl crate::storable::sealed::Sealed for Variant<'_> {}
93
94impl Storable for Variant<'_> {
95 #[inline]
96 fn store_to<B>(self, buf: &mut B)
97 where
98 B: ?Sized + WriteAligned,
99 {
100 buf.write_only(self.contained_signature());
101
102 match self {
103 Variant::Bool(value) => buf.store_frame(u32::from(value)),
104 Variant::U8(value) => buf.store_frame(value),
105 Variant::I16(value) => buf.store_frame(value),
106 Variant::U16(value) => buf.store_frame(value),
107 Variant::I32(value) => buf.store_frame(value),
108 Variant::U32(value) => buf.store_frame(value),
109 Variant::I64(value) => buf.store_frame(value),
110 Variant::U64(value) => buf.store_frame(value),
111 Variant::F64(value) => buf.store_frame(value),
112 Variant::String(value) => buf.write_only(value),
113 Variant::ObjectPath(value) => buf.write_only(value),
114 Variant::Signature(value) => buf.write_only(value),
115 }
116 }
117
118 #[inline]
119 fn write_signature(builder: &mut SignatureBuilder) -> bool {
120 builder.extend_from_signature(Signature::VARIANT)
121 }
122}