tokio_dbus/ty/mod.rs
1//! Type [`Marker`] for writing to type-checked D-Bus bodies.
2//!
3//! # Examples
4//!
5//! ```
6//! use tokio_dbus::{BodyBuf, Endianness};
7//! use tokio_dbus::ty;
8//!
9//! let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
10//! buf.store(10u8);
11//!
12//! buf.store_struct::<(u16, u32, ty::Array<u8>, ty::Str)>()?
13//! .store(10u16)
14//! .store(10u32)
15//! .store_array(|w| {
16//! w.store(1u8);
17//! w.store(2u8);
18//! w.store(3u8);
19//! })
20//! .store("Hello World")
21//! .finish();
22//!
23//! assert_eq!(buf.signature(), b"y(quays)");
24//! assert_eq!(buf.get(), &[10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 3, 0, 0, 0, 1, 2, 3, 0, 11, 0, 0, 0, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0]);
25//! # Ok::<_, tokio_dbus::Error>(())
26//! ```
27
28pub use self::fields::Fields;
29mod fields;
30
31pub use self::r#unsized::Unsized;
32mod r#unsized;
33
34pub use self::marker::Marker;
35pub(crate) mod marker;
36
37pub use self::aligned::Aligned;
38pub(crate) mod aligned;
39
40use core::marker::PhantomData;
41
42use crate::error::ErrorKind;
43use crate::signature::SignatureBuilder;
44use crate::{Body, Error, LoadArray, Result, SignatureError};
45
46/// The [`Marker`] for the [`str`] type.
47///
48/// [`Signature`]: crate::Signature
49///
50/// # Examples
51///
52/// ```
53/// use tokio_dbus::{BodyBuf, Signature};
54/// use tokio_dbus::ty;
55///
56/// let mut buf = BodyBuf::new();
57///
58/// buf.store_struct::<(u8, ty::Str)>()?
59/// .store(42u8)
60/// .store("Hello World!")
61/// .finish();
62///
63/// assert_eq!(buf.signature(), b"(ys)");
64///
65/// let mut b = buf.as_body();
66///
67/// let (n, value) = b.load_struct::<(u8, ty::Str)>()?;
68///
69/// assert_eq!(n, 42u8);
70/// assert_eq!(value, "Hello World!");
71/// # Ok::<_, tokio_dbus::Error>(())
72/// ```
73#[non_exhaustive]
74pub struct Str;
75
76impl_trait_unsized_marker!(Str, u32, str, STRING);
77
78/// The [`Marker`] for the [`Signature`] type.
79///
80/// [`Signature`]: crate::Signature
81///
82/// # Examples
83///
84/// ```
85/// use tokio_dbus::{BodyBuf, Signature};
86/// use tokio_dbus::ty;
87///
88/// let mut buf = BodyBuf::new();
89///
90/// buf.store_struct::<(u8, ty::Signature)>()?
91/// .store(42u8)
92/// .store(Signature::new("ay")?)
93/// .finish();
94///
95/// assert_eq!(buf.signature(), b"(yg)");
96///
97/// let mut b = buf.as_body();
98///
99/// let (n, value) = b.load_struct::<(u8, ty::Signature)>()?;
100///
101/// assert_eq!(n, 42u8);
102/// assert_eq!(value, Signature::new("ay")?);
103/// # Ok::<_, tokio_dbus::Error>(())
104/// ```
105#[non_exhaustive]
106pub struct Signature;
107
108impl_trait_unsized_marker!(Signature, u8, crate::Signature, SIGNATURE);
109
110/// The [`Marker`] for the [`ObjectPath`] type.
111///
112/// [`ObjectPath`]: crate::ObjectPath
113///
114/// # Examples
115///
116/// ```
117/// use tokio_dbus::{BodyBuf, ObjectPath};
118/// use tokio_dbus::ty;
119///
120/// let mut buf = BodyBuf::new();
121///
122/// buf.store_struct::<(u8, ty::ObjectPath)>()?
123/// .store(42u8)
124/// .store(ObjectPath::new("/se/tedro/DBusExample")?)
125/// .finish();
126///
127/// assert_eq!(buf.signature(), b"(yo)");
128///
129/// let mut b = buf.as_body();
130///
131/// let (n, value) = b.load_struct::<(u8, ty::ObjectPath)>()?;
132///
133/// assert_eq!(n, 42u8);
134/// assert_eq!(value, ObjectPath::new("/se/tedro/DBusExample")?);
135/// # Ok::<_, tokio_dbus::Error>(())
136/// ```
137#[non_exhaustive]
138pub struct ObjectPath;
139
140impl_trait_unsized_marker!(ObjectPath, u8, crate::ObjectPath, OBJECT_PATH);
141
142/// The [`Marker`] for an array type, like `[u8]`.
143///
144/// # Examples
145///
146/// ```
147/// use tokio_dbus::{BodyBuf, Signature};
148/// use tokio_dbus::ty;
149///
150/// let mut buf = BodyBuf::new();
151///
152/// buf.store_struct::<(u8, ty::Array<ty::Str>)>()?
153/// .store(42u8)
154/// .store_array(|w| {
155/// w.store("Hello");
156/// w.store("World");
157/// })
158/// .finish();
159///
160/// assert_eq!(buf.signature(), b"(yas)");
161///
162/// let mut b = buf.as_body();
163///
164/// let (n, mut array) = b.load_struct::<(u8, ty::Array<ty::Str>)>()?;
165///
166/// assert_eq!(n, 42u8);
167/// assert_eq!(array.read()?, Some("Hello"));
168/// assert_eq!(array.read()?, Some("World"));
169/// assert_eq!(array.read()?, None);
170/// # Ok::<_, tokio_dbus::Error>(())
171/// ```
172pub struct Array<T>(PhantomData<T>);
173
174impl<T> self::aligned::sealed::Sealed for Array<T> {}
175
176impl<T> Aligned for Array<T> {
177 // NB: An array starts with a 32-bit length prefix, regardless of the
178 // alignment of its elements.
179 type Alignment = u32;
180}
181
182impl<T> self::marker::sealed::Sealed for Array<T> where T: Marker {}
183
184impl<T> Marker for Array<T>
185where
186 T: Marker,
187{
188 type Return<'de> = LoadArray<'de, T>;
189
190 #[inline]
191 fn load_struct<'de>(buf: &mut Body<'de>) -> Result<Self::Return<'de>> {
192 buf.load_array::<T>()
193 }
194
195 #[inline]
196 fn write_signature(signature: &mut SignatureBuilder) -> Result<(), SignatureError> {
197 signature.open_array()?;
198 T::write_signature(signature)?;
199 signature.close_array();
200 Ok(())
201 }
202}
203
204/// The [`Marker`] for a dict entry, which is only legal as the element type of
205/// an [`Array`].
206///
207/// The key `K` must be a basic type.
208///
209/// # Examples
210///
211/// ```
212/// use tokio_dbus::{ty, BodyBuf};
213///
214/// let mut buf = BodyBuf::new();
215///
216/// let mut dict = buf.store_array::<ty::Dict<ty::Str, u32>>()?;
217/// dict.store_entry().store("Hello").store(42u32).finish();
218/// dict.finish();
219///
220/// assert_eq!(buf.signature(), "a{su}");
221///
222/// let mut buf = buf.as_body();
223/// let mut dict = buf.load_array::<ty::Dict<ty::Str, u32>>()?;
224///
225/// assert_eq!(dict.load_entry()?, Some(("Hello", 42)));
226/// assert_eq!(dict.load_entry()?, None);
227/// # Ok::<_, tokio_dbus::Error>(())
228/// ```
229pub struct Dict<K, V>(PhantomData<(K, V)>);
230
231impl<K, V> self::aligned::sealed::Sealed for Dict<K, V> {}
232
233impl<K, V> Aligned for Dict<K, V> {
234 // NB: Dict entries are aligned just like structs.
235 type Alignment = u64;
236}
237
238impl<K, V> self::marker::sealed::Sealed for Dict<K, V>
239where
240 K: Marker,
241 V: Marker,
242{
243}
244
245impl<K, V> Marker for Dict<K, V>
246where
247 K: Marker,
248 V: Marker,
249{
250 type Return<'de> = (K::Return<'de>, V::Return<'de>);
251
252 #[inline]
253 fn load_struct<'de>(buf: &mut Body<'de>) -> Result<Self::Return<'de>> {
254 buf.align::<u64>()?;
255 Ok((K::load_struct(buf)?, V::load_struct(buf)?))
256 }
257
258 #[inline]
259 fn write_signature(signature: &mut SignatureBuilder) -> Result<(), SignatureError> {
260 signature.open_dict()?;
261 K::write_signature(signature)?;
262 V::write_signature(signature)?;
263 signature.close_dict()?;
264 Ok(())
265 }
266}
267
268/// The [`Marker`] for the D-Bus `BOOLEAN` type, which is marshalled as a 32-bit
269/// integer but read and written as a [`bool`].
270///
271/// # Examples
272///
273/// ```
274/// use tokio_dbus::{ty, BodyBuf};
275///
276/// let mut buf = BodyBuf::new();
277///
278/// buf.store_struct::<(ty::Bool, ty::Str)>()?
279/// .store(true)
280/// .store("Hello World!")
281/// .finish();
282///
283/// assert_eq!(buf.signature(), "(bs)");
284///
285/// let mut buf = buf.as_body();
286/// let (enabled, message) = buf.load_struct::<(ty::Bool, ty::Str)>()?;
287///
288/// assert!(enabled);
289/// assert_eq!(message, "Hello World!");
290/// # Ok::<_, tokio_dbus::Error>(())
291/// ```
292#[non_exhaustive]
293pub struct Bool;
294
295impl self::aligned::sealed::Sealed for Bool {}
296
297impl Aligned for Bool {
298 type Alignment = u32;
299}
300
301impl self::marker::sealed::Sealed for Bool {}
302
303impl Marker for Bool {
304 type Return<'de> = bool;
305
306 #[inline]
307 fn load_struct<'de>(buf: &mut Body<'de>) -> Result<Self::Return<'de>> {
308 Ok(buf.load::<u32>()? != 0)
309 }
310
311 #[inline]
312 fn write_signature(signature: &mut SignatureBuilder) -> Result<(), SignatureError> {
313 if !signature.extend_from_signature(crate::Signature::BOOLEAN) {
314 return Err(SignatureError::too_long());
315 }
316
317 Ok(())
318 }
319}
320
321/// The [`Marker`] for the [`Variant`] type.
322///
323/// [`Variant`]: crate::Variant
324#[non_exhaustive]
325pub struct Variant;
326
327impl self::aligned::sealed::Sealed for Variant {}
328
329impl Aligned for Variant {
330 // NB: A variant starts with its signature, which is prefixed by a single
331 // byte holding its length.
332 type Alignment = u8;
333}
334
335impl self::marker::sealed::Sealed for Variant {}
336
337impl Marker for Variant {
338 type Return<'de> = crate::Variant<'de>;
339
340 #[inline]
341 fn load_struct<'de>(buf: &mut Body<'de>) -> Result<Self::Return<'de>> {
342 let signature: &crate::Signature = buf.read()?;
343
344 let variant = match signature.as_bytes() {
345 b"b" => crate::Variant::Bool(buf.load::<u32>()? != 0),
346 b"y" => crate::Variant::U8(buf.load()?),
347 b"n" => crate::Variant::I16(buf.load()?),
348 b"q" => crate::Variant::U16(buf.load()?),
349 b"i" => crate::Variant::I32(buf.load()?),
350 b"u" => crate::Variant::U32(buf.load()?),
351 b"x" => crate::Variant::I64(buf.load()?),
352 b"t" => crate::Variant::U64(buf.load()?),
353 b"d" => crate::Variant::F64(buf.load()?),
354 b"s" => crate::Variant::String(buf.read()?),
355 b"o" => crate::Variant::ObjectPath(buf.read()?),
356 b"g" => crate::Variant::Signature(buf.read()?),
357 #[cfg(feature = "alloc")]
358 _ => {
359 return Err(Error::new(ErrorKind::UnsupportedVariant(signature.into())));
360 }
361 #[cfg(not(feature = "alloc"))]
362 _ => {
363 return Err(Error::new(ErrorKind::UnsupportedVariantNoAlloc));
364 }
365 };
366
367 Ok(variant)
368 }
369
370 #[inline]
371 fn write_signature(signature: &mut SignatureBuilder) -> Result<(), SignatureError> {
372 if !signature.extend_from_signature(crate::Signature::VARIANT) {
373 return Err(SignatureError::too_long());
374 }
375
376 Ok(())
377 }
378}