Skip to main content

tokio_dbus/body_buf/
store_variant.rs

1use crate::ty;
2use crate::{BodyBuf, Signature, Storable};
3
4use super::{StoreArray, StoreStruct};
5
6/// Write the contents of a variant.
7///
8/// The signature of the contained value is written when this is constructed,
9/// after which exactly one value matching that signature must be stored.
10///
11/// Unlike the other writers in this crate a variant is written against a
12/// signature which is provided at runtime. This is what makes it possible to
13/// write recursive types, such as the `(ia{sv}av)` layout of a
14/// `com.canonical.dbusmenu` menu.
15///
16/// See [`BodyBuf::store_variant`].
17///
18/// [`BodyBuf::store_variant`]: crate::BodyBuf::store_variant
19#[must_use = "Writers must be used to store the contents of the variant"]
20pub struct StoreVariant<'a> {
21    buf: &'a mut BodyBuf,
22}
23
24impl<'a> StoreVariant<'a> {
25    pub(crate) fn new(buf: &'a mut BodyBuf, signature: &Signature) -> Self {
26        // NB: The signature of the contained value is written verbatim and is
27        // not part of the signature of the surrounding buffer.
28        buf.write_only(signature);
29        Self { buf }
30    }
31
32    /// Store a value inside of the variant.
33    ///
34    /// Note that a [`Variant`] must *not* be stored this way, since it writes
35    /// its own signature and would end up writing it twice. Store it directly
36    /// instead, with [`BodyBuf::store`] or the `store` of the surrounding
37    /// container.
38    ///
39    /// [`Variant`]: crate::Variant
40    /// [`BodyBuf::store`]: crate::BodyBuf::store
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use tokio_dbus::{BodyBuf, Signature, Variant};
46    ///
47    /// let mut buf = BodyBuf::new();
48    /// buf.store_variant(Signature::STRING)?.store("Hello World!");
49    ///
50    /// assert_eq!(buf.signature(), Signature::VARIANT);
51    ///
52    /// let mut buf = buf.as_body();
53    /// assert_eq!(buf.read_variant()?, Variant::String("Hello World!"));
54    /// # Ok::<_, tokio_dbus::Error>(())
55    /// ```
56    #[inline]
57    pub fn store<T>(self, value: T)
58    where
59        T: Storable,
60    {
61        value.store_to(self.buf);
62    }
63
64    /// Store an array inside of the variant.
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use tokio_dbus::{ty, BodyBuf, Signature};
70    ///
71    /// let mut buf = BodyBuf::new();
72    ///
73    /// let mut array = buf.store_variant(Signature::new("as")?)?.store_array::<ty::Str>();
74    /// array.store("Hello");
75    /// array.store("World");
76    /// array.finish();
77    ///
78    /// assert_eq!(buf.signature(), Signature::VARIANT);
79    ///
80    /// let mut buf = buf.as_body();
81    /// assert_eq!(buf.skip_variant()?, Signature::new("as")?);
82    /// # Ok::<_, tokio_dbus::Error>(())
83    /// ```
84    #[inline]
85    pub fn store_array<E>(self) -> StoreArray<'a, E>
86    where
87        E: ty::Aligned,
88    {
89        StoreArray::new(self.buf)
90    }
91
92    /// Store a struct inside of the variant.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use tokio_dbus::{ty, BodyBuf, Signature};
98    ///
99    /// let mut buf = BodyBuf::new();
100    ///
101    /// buf.store_variant(Signature::new("(us)")?)?
102    ///     .store_struct::<(u32, ty::Str)>()
103    ///     .store(42u32)
104    ///     .store("Hello World!")
105    ///     .finish();
106    ///
107    /// assert_eq!(buf.signature(), Signature::VARIANT);
108    ///
109    /// let mut buf = buf.as_body();
110    /// assert_eq!(buf.skip_variant()?, Signature::new("(us)")?);
111    /// # Ok::<_, tokio_dbus::Error>(())
112    /// ```
113    #[inline]
114    pub fn store_struct<F>(self) -> StoreStruct<'a, F>
115    where
116        F: ty::Fields,
117    {
118        StoreStruct::new(self.buf)
119    }
120}