Skip to main content

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}