tokio_dbus/body/mod.rs
1pub use self::load_array::LoadArray;
2mod load_array;
3
4pub use self::as_body::AsBody;
5mod as_body;
6
7use core::fmt;
8
9#[cfg(feature = "alloc")]
10use crate::BodyBuf;
11use crate::buf::Aligned;
12use crate::error::Result;
13use crate::ty;
14use crate::{Endianness, Frame, Read, Signature};
15
16/// A read-only view into a buffer suitable for use as a body in a [`Message`].
17///
18/// [`Message`]: crate::Message
19///
20/// # Examples
21///
22/// ```
23/// use tokio_dbus::{Result, Body};
24///
25/// fn read(buf: &mut Body<'_>) -> Result<()> {
26/// assert_eq!(buf.load::<u32>()?, 7u32);
27/// assert_eq!(buf.load::<u8>()?, b'f');
28/// assert_eq!(buf.load::<u8>()?, b'o');
29/// assert_eq!(buf.get(), &[b'o', b' ', b'b', b'a', b'r', 0]);
30/// Ok(())
31/// }
32/// # Ok::<_, tokio_dbus::Error>(())
33/// ```
34pub struct Body<'a> {
35 data: Aligned<'a>,
36 endianness: Endianness,
37 signature: &'a Signature,
38}
39
40impl<'a> Body<'a> {
41 /// Construct an empty buffer.
42 pub(crate) const fn empty() -> Self {
43 Self::from_raw_parts(Aligned::empty(), Endianness::NATIVE, Signature::EMPTY)
44 }
45
46 /// Construct a new buffer wrapping pointed to data.
47 #[inline]
48 pub(crate) const fn from_raw_parts(
49 data: Aligned<'a>,
50 endianness: Endianness,
51 signature: &'a Signature,
52 ) -> Self {
53 Self {
54 data,
55 endianness,
56 signature,
57 }
58 }
59
60 /// Deconstruct into raw parts.
61 #[cfg(feature = "alloc")]
62 #[inline]
63 pub(crate) const fn into_raw_parts(self) -> (Aligned<'a>, Endianness, &'a Signature) {
64 (self.data, self.endianness, self.signature)
65 }
66
67 /// Get the endianness of the buffer.
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use tokio_dbus::{Body, BodyBuf, Endianness};
73 ///
74 /// let buf = BodyBuf::new();
75 ///
76 /// let buf: Body<'_> = buf.as_body();
77 /// assert_eq!(buf.endianness(), Endianness::NATIVE);
78 ///
79 /// let buf = buf.with_endianness(Endianness::BIG);
80 /// assert_eq!(buf.endianness(), Endianness::BIG);
81 /// # Ok::<_, tokio_dbus::Error>(())
82 /// ```
83 pub fn endianness(&self) -> Endianness {
84 self.endianness
85 }
86
87 /// Adjust endianness of buffer.
88 ///
89 /// # Examples
90 ///
91 /// ```
92 /// use tokio_dbus::{Body, BodyBuf, Endianness};
93 ///
94 /// let buf = BodyBuf::new();
95 ///
96 /// let buf: Body<'_> = buf.as_body();
97 /// assert_eq!(buf.endianness(), Endianness::NATIVE);
98 ///
99 /// let buf = buf.with_endianness(Endianness::BIG);
100 /// assert_eq!(buf.endianness(), Endianness::BIG);
101 /// # Ok::<_, tokio_dbus::Error>(())
102 /// ```
103 pub fn with_endianness(self, endianness: Endianness) -> Self {
104 Self { endianness, ..self }
105 }
106
107 /// Get the signature of the buffer.
108 ///
109 /// # Examples
110 ///
111 /// ```
112 /// use tokio_dbus::{Body, BodyBuf};
113 ///
114 /// let mut buf = BodyBuf::new();
115 ///
116 /// buf.store(10u16)?;
117 /// buf.store(10u32)?;
118 ///
119 /// let buf: Body<'_> = buf.as_body();
120 ///
121 /// assert_eq!(buf.signature(), "qu");
122 /// # Ok::<_, tokio_dbus::Error>(())
123 /// ```
124 pub fn signature(&self) -> &'a Signature {
125 self.signature
126 }
127
128 /// Adjust the signature of buffer.
129 #[cfg(feature = "alloc")]
130 pub(crate) fn with_signature(self, signature: &'a Signature) -> Self {
131 Self { signature, ..self }
132 }
133
134 /// Get a slice out of the buffer that has ben written to.
135 ///
136 /// # Examples
137 ///
138 /// ```
139 /// use tokio_dbus::{Result, Body};
140 ///
141 /// fn read(buf: &mut Body<'_>) -> Result<()> {
142 /// assert_eq!(buf.load::<u32>()?, 7u32);
143 /// assert_eq!(buf.load::<u8>()?, b'f');
144 /// assert_eq!(buf.load::<u8>()?, b'o');
145 /// assert_eq!(buf.get(), &[b'o', b' ', b'b', b'a', b'r', 0]);
146 /// Ok(())
147 /// }
148 /// # Ok::<_, tokio_dbus::Error>(())
149 /// ```
150 pub fn get(&self) -> &'a [u8] {
151 self.data.get()
152 }
153
154 /// Test if the buffer is empty.
155 ///
156 /// # Examples
157 ///
158 /// ```
159 /// use tokio_dbus::{Body, BodyBuf, Endianness};
160 ///
161 /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
162 /// let b: Body<'_> = buf.as_body();
163 /// assert!(b.is_empty());
164 ///
165 /// buf.store(10u16)?;
166 /// buf.store(10u32)?;
167 ///
168 /// let b: Body<'_> = buf.as_body();
169 /// assert!(!b.is_empty());
170 /// # Ok::<_, tokio_dbus::Error>(())
171 /// ```
172 #[inline]
173 pub fn is_empty(&self) -> bool {
174 self.data.is_empty()
175 }
176
177 /// Remaining data to be read from the buffer.
178 ///
179 /// # Examples
180 ///
181 /// ```
182 /// use tokio_dbus::{Body, BodyBuf, Endianness};
183 ///
184 /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
185 /// assert!(buf.is_empty());
186 ///
187 /// buf.store(10u16)?;
188 /// buf.store(10u32)?;
189 ///
190 /// let b: Body<'_> = buf.as_body();
191 /// assert_eq!(b.len(), 8);
192 /// # Ok::<_, tokio_dbus::Error>(())
193 /// ```
194 #[inline]
195 pub fn len(&self) -> usize {
196 self.data.len()
197 }
198
199 /// Read a reference from the buffer.
200 ///
201 /// This is possible for unaligned types such as `str` and `[u8]` which
202 /// implement [`Read`].
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// use tokio_dbus::{Result, Body};
208 ///
209 /// fn read(buf: &mut Body<'_>) -> Result<()> {
210 /// assert_eq!(buf.load::<u32>()?, 4);
211 /// assert_eq!(buf.read::<str>()?, "hi");
212 /// assert!(buf.is_empty());
213 /// Ok(())
214 /// }
215 /// # Ok::<_, tokio_dbus::Error>(())
216 /// ````
217 pub fn read<T>(&mut self) -> Result<&'a T>
218 where
219 T: ?Sized + Read,
220 {
221 T::read_from(self)
222 }
223
224 /// Read `len` bytes from the buffer and make accessible through another
225 /// [`Body`] instance constituting that sub-slice.
226 ///
227 /// # Panics
228 ///
229 /// This panics if `len` is larger than [`len()`].
230 ///
231 /// [`len()`]: Self::len
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// use tokio_dbus::{Result, Body};
237 ///
238 /// fn read(buf: &mut Body<'_>) -> Result<()> {
239 /// let mut read_buf = buf.read_until(6);
240 /// assert_eq!(read_buf.load::<u32>()?, 4);
241 ///
242 /// let mut read_buf2 = read_buf.read_until(2);
243 /// assert_eq!(read_buf2.load::<u8>()?, 1);
244 /// assert_eq!(read_buf2.load::<u8>()?, 2);
245 ///
246 /// assert!(read_buf.is_empty());
247 /// assert!(read_buf2.is_empty());
248 ///
249 /// assert_eq!(buf.get(), &[3, 4, 0]);
250 /// Ok(())
251 /// }
252 /// ```
253 pub fn read_until(&mut self, len: usize) -> Body<'a> {
254 Body::from_raw_parts(self.data.read_until(len), self.endianness, self.signature)
255 }
256
257 /// Read an array from the buffer.
258 ///
259 /// # Examples
260 ///
261 /// ```
262 /// use tokio_dbus::{ty, BodyBuf, Endianness};
263 ///
264 /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
265 /// let mut array = buf.store_array::<u32>()?;
266 /// array.store(10u32);
267 /// array.store(20u32);
268 /// array.store(30u32);
269 /// array.finish();
270 ///
271 /// let mut array = buf.store_array::<ty::Array<ty::Str>>()?;
272 /// let mut inner = array.store_array();
273 /// inner.store("foo");
274 /// inner.store("bar");
275 /// inner.store("baz");
276 /// inner.finish();
277 /// array.finish();
278 ///
279 /// assert_eq!(buf.signature(), b"auaas");
280 ///
281 /// let mut buf = buf.as_body();
282 /// let mut array = buf.load_array::<u32>()?;
283 /// assert_eq!(array.load()?, Some(10));
284 /// assert_eq!(array.load()?, Some(20));
285 /// assert_eq!(array.load()?, Some(30));
286 /// assert_eq!(array.load()?, None);
287 ///
288 /// let mut array = buf.load_array::<ty::Array<ty::Str>>()?;
289 ///
290 /// let Some(mut inner) = array.load_array()? else {
291 /// panic!("Missing inner array");
292 /// };
293 ///
294 /// assert_eq!(inner.read()?, Some("foo"));
295 /// assert_eq!(inner.read()?, Some("bar"));
296 /// assert_eq!(inner.read()?, Some("baz"));
297 /// assert_eq!(inner.read()?, None);
298 /// # Ok::<_, tokio_dbus::Error>(())
299 /// ```
300 pub fn load_array<E>(&mut self) -> Result<LoadArray<'a, E>>
301 where
302 E: ty::Marker,
303 {
304 LoadArray::from_mut(self)
305 }
306
307 /// Read a struct from the buffer.
308 ///
309 /// # Examples
310 ///
311 /// ```
312 /// use tokio_dbus::{ty, BodyBuf, Endianness};
313 ///
314 /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
315 /// buf.store(10u8);
316 ///
317 /// buf.store_struct::<(u16, u32, ty::Array<u8>, ty::Str)>()?
318 /// .store(20u16)
319 /// .store(30u32)
320 /// .store_array(|w| {
321 /// w.store(1u8);
322 /// w.store(2u8);
323 /// w.store(3u8);
324 /// })
325 /// .store("Hello World")
326 /// .finish();
327 ///
328 /// assert_eq!(buf.signature(), "y(quays)");
329 ///
330 /// let mut buf = buf.as_body();
331 /// assert_eq!(buf.load::<u8>()?, 10u8);
332 ///
333 /// let (a, b, mut array, string) = buf.load_struct::<(u16, u32, ty::Array<u8>, ty::Str)>()?;
334 /// assert_eq!(a, 20u16);
335 /// assert_eq!(b, 30u32);
336 ///
337 /// assert_eq!(array.load()?, Some(1));
338 /// assert_eq!(array.load()?, Some(2));
339 /// assert_eq!(array.load()?, Some(3));
340 /// assert_eq!(array.load()?, None);
341 ///
342 /// assert_eq!(string, "Hello World");
343 /// # Ok::<_, tokio_dbus::Error>(())
344 /// ```
345 pub fn load_struct<E>(&mut self) -> Result<E::Return<'a>>
346 where
347 E: ty::Fields,
348 {
349 self.align::<u64>()?;
350 E::load_struct(self)
351 }
352
353 /// Read a struct whose fields are read by the given closure.
354 ///
355 /// This aligns the buffer as a struct and then hands it to `f`. It is an
356 /// escape hatch for structs which [`load_struct()`] cannot describe, such as
357 /// ones containing a variant of an unknown type.
358 ///
359 /// [`load_struct()`]: Self::load_struct
360 ///
361 /// # Examples
362 ///
363 /// ```
364 /// use tokio_dbus::{ty, BodyBuf, Signature};
365 ///
366 /// let mut buf = BodyBuf::new();
367 ///
368 /// buf.store_struct::<(u32, ty::Variant)>()?
369 /// .store(42u32)
370 /// .store_variant(Signature::new("as")?, |w| {
371 /// w.store_array::<ty::Str>().store("Hello");
372 /// })
373 /// .finish();
374 ///
375 /// let mut buf = buf.as_body();
376 ///
377 /// let n = buf.load_struct_with(|b| {
378 /// let n = b.load::<u32>()?;
379 /// b.skip_variant()?;
380 /// Ok(n)
381 /// })?;
382 ///
383 /// assert_eq!(n, 42);
384 /// # Ok::<_, tokio_dbus::Error>(())
385 /// ```
386 pub fn load_struct_with<F, O>(&mut self, f: F) -> Result<O>
387 where
388 F: FnOnce(&mut Body<'a>) -> Result<O>,
389 {
390 self.align::<u64>()?;
391 f(self)
392 }
393
394 /// Load a frame of the given type.
395 ///
396 /// This advances the read cursor of the buffer by the alignment and size of
397 /// the type. The return value has been endian-adjusted as per
398 /// [`endianness()`].
399 ///
400 /// [`endianness()`]: Self::endianness
401 ///
402 /// # Error
403 ///
404 /// Errors if the underlying buffer does not have enough space to represent
405 /// the type `T`.
406 ///
407 /// # Examples
408 ///
409 /// ```
410 /// use tokio_dbus::{Result, Body};
411 ///
412 /// fn read(buf: &mut Body<'_>) -> Result<()> {
413 /// assert_eq!(buf.load::<u32>()?, 7u32);
414 /// assert_eq!(buf.load::<u8>()?, b'f');
415 /// assert_eq!(buf.load::<u8>()?, b'o');
416 /// assert_eq!(buf.get(), &[b'o', b' ', b'b', b'a', b'r', 0]);
417 /// Ok(())
418 /// }
419 /// # Ok::<_, tokio_dbus::Error>(())
420 /// ```
421 pub fn load<T>(&mut self) -> Result<T>
422 where
423 T: Frame,
424 {
425 let mut frame = self.data.load::<T>()?;
426 frame.adjust(self.endianness);
427 Ok(frame)
428 }
429
430 /// Load a [`bool`] from the buffer.
431 ///
432 /// The D-Bus `BOOLEAN` type is marshalled as a 32-bit integer, which is why
433 /// it cannot be loaded through [`load()`].
434 ///
435 /// [`load()`]: Self::load
436 ///
437 /// # Examples
438 ///
439 /// ```
440 /// use tokio_dbus::BodyBuf;
441 ///
442 /// let mut buf = BodyBuf::new();
443 /// buf.store(true)?;
444 /// buf.store(false)?;
445 ///
446 /// let mut buf = buf.as_body();
447 /// assert!(buf.load_bool()?);
448 /// assert!(!buf.load_bool()?);
449 /// # Ok::<_, tokio_dbus::Error>(())
450 /// ```
451 pub fn load_bool(&mut self) -> Result<bool> {
452 Ok(self.load::<u32>()? != 0)
453 }
454
455 /// Read a [`Variant`] holding a value of a basic type from the buffer.
456 ///
457 /// [`Variant`]: crate::Variant
458 ///
459 /// # Errors
460 ///
461 /// Errors if the variant holds a container. Use [`skip_variant()`] to skip
462 /// over a variant of an unknown type instead.
463 ///
464 /// [`skip_variant()`]: Self::skip_variant
465 ///
466 /// # Examples
467 ///
468 /// ```
469 /// use tokio_dbus::{BodyBuf, Variant};
470 ///
471 /// let mut buf = BodyBuf::new();
472 /// buf.store(Variant::U32(42))?;
473 ///
474 /// let mut buf = buf.as_body();
475 /// assert_eq!(buf.read_variant()?, Variant::U32(42));
476 /// # Ok::<_, tokio_dbus::Error>(())
477 /// ```
478 pub fn read_variant(&mut self) -> Result<crate::Variant<'a>> {
479 <ty::Variant as ty::Marker>::load_struct(self)
480 }
481
482 /// Read a variant which is expected to contain a value of type `T`.
483 ///
484 /// Unlike [`read_variant()`] this can read containers, but requires the
485 /// caller to know which type the variant contains.
486 ///
487 /// [`read_variant()`]: Self::read_variant
488 ///
489 /// # Errors
490 ///
491 /// Errors if the variant does not contain a value of type `T`.
492 ///
493 /// # Examples
494 ///
495 /// ```
496 /// use tokio_dbus::{ty, BodyBuf, Signature};
497 ///
498 /// let mut buf = BodyBuf::new();
499 ///
500 /// let mut array = buf.store_variant(Signature::new("as")?)?.store_array::<ty::Str>();
501 /// array.store("Hello");
502 /// array.store("World");
503 /// array.finish();
504 ///
505 /// let mut buf = buf.as_body();
506 /// let mut array = buf.read_variant_as::<ty::Array<ty::Str>>()?;
507 ///
508 /// assert_eq!(array.read()?, Some("Hello"));
509 /// assert_eq!(array.read()?, Some("World"));
510 /// assert_eq!(array.read()?, None);
511 /// # Ok::<_, tokio_dbus::Error>(())
512 /// ```
513 pub fn read_variant_as<T>(&mut self) -> Result<T::Return<'a>>
514 where
515 T: ty::Marker,
516 {
517 let signature = self.read::<Signature>()?;
518
519 let mut expected = crate::signature::SignatureBuilder::new();
520 T::write_signature(&mut expected)?;
521
522 if signature != expected.to_signature() {
523 #[cfg(feature = "alloc")]
524 return Err(crate::Error::new(
525 crate::error::ErrorKind::UnsupportedVariant(signature.into()),
526 ));
527 #[cfg(not(feature = "alloc"))]
528 return Err(crate::Error::new(
529 crate::error::ErrorKind::UnsupportedVariantNoAlloc,
530 ));
531 }
532
533 self.align::<T::Alignment>()?;
534 T::load_struct(self)
535 }
536
537 /// Skip over a variant of any type, returning the signature of the value it
538 /// contained.
539 ///
540 /// This is useful for arguments which are declared as variants but which
541 /// the receiver has no interest in, such as the `data` argument of the
542 /// `com.canonical.dbusmenu.Event` method.
543 ///
544 /// # Examples
545 ///
546 /// ```
547 /// use tokio_dbus::{ty, BodyBuf, Signature};
548 ///
549 /// let mut buf = BodyBuf::new();
550 ///
551 /// buf.store_variant(Signature::new("as")?)?
552 /// .store_array::<ty::Str>()
553 /// .store("Hello");
554 /// buf.store(42u32)?;
555 ///
556 /// assert_eq!(buf.signature(), "vu");
557 ///
558 /// let mut buf = buf.as_body();
559 /// assert_eq!(buf.skip_variant()?, Signature::new("as")?);
560 /// assert_eq!(buf.load::<u32>()?, 42);
561 /// # Ok::<_, tokio_dbus::Error>(())
562 /// ```
563 #[cfg(feature = "alloc")]
564 pub fn skip_variant(&mut self) -> Result<&'a Signature> {
565 let signature = self.read::<Signature>()?;
566 crate::signature::skip(signature, self)?;
567 Ok(signature)
568 }
569
570 /// Align the read cursor to the given alignment.
571 ///
572 /// This is the counterpart of [`Raw::align`], and is needed before reading
573 /// the fields of a struct or a dict entry whose shape is only known at
574 /// runtime.
575 ///
576 /// [`Raw::align`]: crate::Raw::align
577 ///
578 /// # Examples
579 ///
580 /// ```
581 /// use tokio_dbus::{ty, Alignment, BodyBuf};
582 ///
583 /// let mut buf = BodyBuf::new();
584 ///
585 /// buf.store(1u8)?;
586 /// buf.store_struct::<(u32, u32)>()?.store(2u32).store(3u32).finish();
587 ///
588 /// let mut buf = buf.as_body();
589 /// assert_eq!(buf.load::<u8>()?, 1);
590 ///
591 /// buf.align_to(Alignment::U64)?;
592 /// assert_eq!(buf.load::<u32>()?, 2);
593 /// assert_eq!(buf.load::<u32>()?, 3);
594 /// # Ok::<_, tokio_dbus::Error>(())
595 /// ```
596 #[cfg(feature = "alloc")]
597 pub fn align_to(&mut self, alignment: crate::Alignment) -> Result<()> {
598 self.data.align_to(alignment.in_bytes())
599 }
600
601 /// Read an array whose elements have the given alignment, returning a
602 /// [`Body`] over its contents.
603 ///
604 /// This is the counterpart of [`Raw::store_array`].
605 ///
606 /// [`Raw::store_array`]: crate::Raw::store_array
607 ///
608 /// # Examples
609 ///
610 /// ```
611 /// use tokio_dbus::{ty, Alignment, BodyBuf};
612 ///
613 /// let mut buf = BodyBuf::new();
614 ///
615 /// let mut array = buf.store_array::<ty::Str>()?;
616 /// array.store("Hello");
617 /// array.store("World");
618 /// array.finish();
619 ///
620 /// let mut buf = buf.as_body();
621 /// let mut array = buf.load_raw_array(Alignment::U32)?;
622 ///
623 /// let mut out = Vec::new();
624 ///
625 /// while !array.is_empty() {
626 /// out.push(array.read::<str>()?);
627 /// }
628 ///
629 /// assert_eq!(out, ["Hello", "World"]);
630 /// # Ok::<_, tokio_dbus::Error>(())
631 /// ```
632 #[cfg(feature = "alloc")]
633 pub fn load_raw_array(&mut self, alignment: crate::Alignment) -> Result<Body<'a>> {
634 let bytes = self.load::<u32>()?;
635
636 if bytes > crate::buf::MAX_ARRAY_LENGTH {
637 return Err(crate::Error::new(crate::error::ErrorKind::ArrayTooLong(
638 bytes,
639 )));
640 }
641
642 self.align_to(alignment)?;
643 Ok(self.read_until(bytes as usize))
644 }
645
646 /// Advance the read cursor by `n`.
647 #[cfg(feature = "alloc")]
648 #[inline]
649 pub(crate) fn advance(&mut self, n: usize) -> Result<()> {
650 self.data.advance(n)
651 }
652
653 /// Align the read side of the buffer.
654 #[inline]
655 pub(crate) fn align<T>(&mut self) -> Result<()> {
656 self.data.align::<T>()
657 }
658
659 /// Load a slice.
660 #[inline]
661 pub(crate) fn load_slice(&mut self, len: usize) -> Result<&'a [u8]> {
662 self.data.load_slice(len)
663 }
664
665 /// Load a slice ending with a NUL byte, excluding the null byte.
666 #[inline]
667 pub(crate) fn load_slice_nul(&mut self, len: usize) -> Result<&'a [u8]> {
668 self.data.load_slice_nul(len)
669 }
670}
671
672// SAFETY: Body is equivalent to `&[u8]`.
673unsafe impl Send for Body<'_> {}
674// SAFETY: Body is equivalent to `&[u8]`.
675unsafe impl Sync for Body<'_> {}
676
677impl Clone for Body<'_> {
678 #[inline]
679 fn clone(&self) -> Self {
680 Self {
681 data: self.data.clone(),
682 endianness: self.endianness,
683 signature: self.signature,
684 }
685 }
686}
687
688impl fmt::Debug for Body<'_> {
689 #[inline]
690 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
691 f.debug_struct("Body")
692 .field("data", &self.data)
693 .field("endianness", &self.endianness)
694 .finish()
695 }
696}
697
698impl<'a> PartialEq<Body<'a>> for Body<'_> {
699 #[inline]
700 fn eq(&self, other: &Body<'a>) -> bool {
701 self.get() == other.get() && self.endianness == other.endianness
702 }
703}
704
705#[cfg(feature = "alloc")]
706impl PartialEq<BodyBuf> for Body<'_> {
707 #[inline]
708 fn eq(&self, other: &BodyBuf) -> bool {
709 self.get() == other.get() && self.endianness == other.endianness()
710 }
711}
712
713impl Eq for Body<'_> {}