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}