Skip to main content

tokio_dbus/body_buf/
store_struct.rs

1use std::marker::PhantomData;
2
3use crate::ty;
4use crate::{Arguments, BodyBuf, Signature, Storable};
5
6use super::{StoreArray, StoreVariant};
7
8/// Write a struct.
9///
10/// See [`BodyBuf::store_struct`].
11///
12/// [`BodyBuf::store_struct`]: crate::BodyBuf::store_struct
13#[must_use = "Must call `finish` after writing all related fields"]
14pub struct StoreStruct<'a, T> {
15    buf: &'a mut BodyBuf,
16    _marker: PhantomData<T>,
17}
18
19impl<'a, T> StoreStruct<'a, T> {
20    pub(crate) fn new(buf: &'a mut BodyBuf) -> Self {
21        buf.align_mut::<u64>();
22        Self::inner(buf)
23    }
24
25    pub(crate) fn inner(buf: &'a mut BodyBuf) -> Self {
26        Self {
27            buf,
28            _marker: PhantomData,
29        }
30    }
31
32    /// Store a value and return the builder for the next value to store.
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// use tokio_dbus::{BodyBuf, Endianness};
38    /// use tokio_dbus::ty;
39    ///
40    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
41    ///
42    /// buf.store_struct::<(u16, u32)>()?
43    ///     .store(10u16)
44    ///     .store(10u32)
45    ///     .finish();
46    ///
47    /// assert_eq!(buf.signature(), b"(qu)");
48    /// assert_eq!(buf.get(), &[10, 0, 0, 0, 10, 0, 0, 0]);
49    /// # Ok::<_, tokio_dbus::Error>(())
50    /// ```
51    ///
52    /// Examples using unsized types:
53    ///
54    /// ```
55    /// use tokio_dbus::{BodyBuf, Endianness};
56    /// use tokio_dbus::ty;
57    ///
58    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
59    ///
60    /// buf.store_struct::<(ty::Str,)>()?
61    ///     .store("Hello World")
62    ///     .finish();
63    ///
64    /// assert_eq!(buf.signature(), b"(s)");
65    /// assert_eq!(buf.get(), &[11, 0, 0, 0, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0]);
66    /// # Ok::<_, tokio_dbus::Error>(())
67    /// ```
68    #[inline]
69    pub fn store(self, value: <T::First as ty::Marker>::Return<'_>) -> StoreStruct<'a, T::Remaining>
70    where
71        T: ty::Fields,
72        T::First: ty::Marker,
73        for<'b> <T::First as ty::Marker>::Return<'b>: Storable,
74    {
75        value.store_to(self.buf);
76        StoreStruct::inner(self.buf)
77    }
78
79    /// Store a value and return the builder for the next value to store.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use tokio_dbus::{BodyBuf, Endianness};
85    /// use tokio_dbus::ty;
86    ///
87    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
88    ///
89    /// buf.store_struct::<(u8, u32)>()?.fields((42u8, 42u32));
90    ///
91    /// assert_eq!(buf.signature(), b"(yu)");
92    /// assert_eq!(buf.get(), &[42, 0, 0, 0, 42, 0, 0, 0]);
93    /// # Ok::<_, tokio_dbus::Error>(())
94    /// ```
95    #[inline]
96    pub fn fields(self, arguments: T)
97    where
98        T: Arguments,
99    {
100        arguments.buf_to(self.buf);
101    }
102
103    /// Store a value and return the builder for the next value to store.
104    ///
105    /// # Examples
106    ///
107    /// ```
108    /// use tokio_dbus::{BodyBuf, Endianness};
109    /// use tokio_dbus::ty;
110    ///
111    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
112    ///
113    /// buf.store_struct::<(ty::Array<u32>,)>()?
114    ///     .store_array(|w| {
115    ///         w.store(1);
116    ///         w.store(2);
117    ///         w.store(3);
118    ///         w.store(4);
119    ///     })
120    ///     .finish();
121    ///
122    /// assert_eq!(buf.signature(), b"(au)");
123    /// assert_eq!(buf.get(), &[16, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]);
124    /// # Ok::<_, tokio_dbus::Error>(())
125    /// ```
126    #[inline]
127    pub fn store_array<W, U>(self, writer: W) -> StoreStruct<'a, T::Remaining>
128    where
129        W: FnOnce(&mut StoreArray<'_, U>),
130        T: ty::Fields<First = ty::Array<U>>,
131        U: ty::Aligned,
132    {
133        let mut w = StoreArray::new(self.buf);
134        writer(&mut w);
135        w.finish();
136        StoreStruct::inner(self.buf)
137    }
138
139    /// Store a nested struct and return the builder for the next value to
140    /// store.
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use tokio_dbus::{BodyBuf, Endianness};
146    /// use tokio_dbus::ty;
147    ///
148    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
149    ///
150    /// buf.store_struct::<((u32, ty::Str), u8)>()?
151    ///     .store_struct(|w| {
152    ///         w.store(42u32).store("Hello World").finish();
153    ///     })
154    ///     .store(1u8)
155    ///     .finish();
156    ///
157    /// assert_eq!(buf.signature(), b"((us)y)");
158    ///
159    /// let mut buf = buf.as_body();
160    /// let ((n, string), b) = buf.load_struct::<((u32, ty::Str), u8)>()?;
161    ///
162    /// assert_eq!(n, 42);
163    /// assert_eq!(string, "Hello World");
164    /// assert_eq!(b, 1);
165    /// # Ok::<_, tokio_dbus::Error>(())
166    /// ```
167    #[inline]
168    pub fn store_struct<W>(self, writer: W) -> StoreStruct<'a, T::Remaining>
169    where
170        W: FnOnce(StoreStruct<'_, T::First>),
171        T: ty::Fields,
172        T::First: ty::Fields,
173    {
174        writer(StoreStruct::new(self.buf));
175        StoreStruct::inner(self.buf)
176    }
177
178    /// Store a variant and return the builder for the next value to store.
179    ///
180    /// # Examples
181    ///
182    /// ```
183    /// use tokio_dbus::{ty, BodyBuf, Signature, Variant};
184    ///
185    /// let mut buf = BodyBuf::new();
186    ///
187    /// buf.store_struct::<(u32, ty::Variant)>()?
188    ///     .store(42u32)
189    ///     .store_variant(Signature::STRING, |w| w.store("Hello World!"))
190    ///     .finish();
191    ///
192    /// assert_eq!(buf.signature(), "(uv)");
193    ///
194    /// let mut buf = buf.as_body();
195    /// let (n, value) = buf.load_struct::<(u32, ty::Variant)>()?;
196    ///
197    /// assert_eq!(n, 42);
198    /// assert_eq!(value, Variant::String("Hello World!"));
199    /// # Ok::<_, tokio_dbus::Error>(())
200    /// ```
201    #[inline]
202    pub fn store_variant<W>(self, signature: &Signature, writer: W) -> StoreStruct<'a, T::Remaining>
203    where
204        W: FnOnce(StoreVariant<'_>),
205        T: ty::Fields<First = ty::Variant>,
206    {
207        writer(StoreVariant::new(self.buf, signature));
208        StoreStruct::inner(self.buf)
209    }
210}
211
212impl StoreStruct<'_, ()> {
213    /// Finish writing the struct.
214    ///
215    /// See [`BodyBuf::store_struct`].
216    ///
217    /// [`BodyBuf::store_struct`]: crate::BodyBuf::store_struct
218    pub fn finish(self) {}
219}