Skip to main content

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}