Skip to main content

tokio_dbus/body_buf/
mod.rs

1pub use self::store_array::StoreArray;
2mod store_array;
3
4pub use self::store_struct::StoreStruct;
5mod store_struct;
6
7pub use self::store_variant::StoreVariant;
8mod store_variant;
9
10pub use self::raw::{Raw, RawArray};
11mod raw;
12
13#[cfg(test)]
14mod tests;
15
16use core::fmt;
17
18use alloc::borrow::ToOwned;
19
20use crate::arguments::Arguments;
21use crate::buf::{AlignedBuf, Alloc};
22use crate::error::Result;
23use crate::signature::{SignatureBuilder, SignatureError};
24use crate::ty;
25use crate::{Body, Endianness, Frame, Signature, SignatureBuf, Storable, Write, WriteAligned};
26
27/// A buffer that can be used to write a body.
28///
29/// # Examples
30///
31/// ```
32/// use tokio_dbus::BodyBuf;
33///
34/// let mut body = BodyBuf::new();
35///
36/// body.store(10u16)?;
37/// body.store(10u32)?;
38///
39/// assert_eq!(body.signature(), "qu");
40/// # Ok::<_, tokio_dbus::Error>(())
41/// ```
42#[derive(Clone, PartialEq, Eq)]
43pub struct BodyBuf {
44    buf: AlignedBuf,
45    endianness: Endianness,
46    signature: SignatureBuilder,
47}
48
49impl BodyBuf {
50    /// Construct a new empty body buffer.
51    ///
52    /// # Examples
53    ///
54    /// ```
55    /// use tokio_dbus::BodyBuf;
56    ///
57    /// let mut body = BodyBuf::new();
58    ///
59    /// body.store(10u16)?;
60    /// body.store(10u32)?;
61    ///
62    /// assert_eq!(body.signature(), "qu");
63    /// # Ok::<_, tokio_dbus::Error>(())
64    /// ```
65    pub fn new() -> Self {
66        Self::with_endianness(Endianness::NATIVE)
67    }
68
69    /// Construct a body buffer from its raw parts.
70    pub(crate) fn from_raw_parts(
71        buf: AlignedBuf,
72        endianness: Endianness,
73        signature: SignatureBuf,
74    ) -> Self {
75        Self {
76            buf,
77            endianness,
78            signature: SignatureBuilder::from_owned_signature(signature),
79        }
80    }
81
82    /// Construct a new buffer with the specified endianness.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use tokio_dbus::{BodyBuf, Endianness};
88    ///
89    /// let buf = BodyBuf::with_endianness(Endianness::LITTLE);
90    /// ```
91    pub fn with_endianness(endianness: Endianness) -> Self {
92        Self {
93            signature: SignatureBuilder::new(),
94            endianness,
95            buf: AlignedBuf::new(),
96        }
97    }
98
99    /// Clear the buffer.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use tokio_dbus::BodyBuf;
105    ///
106    /// let mut body = BodyBuf::new();
107    ///
108    /// body.store(10u16)?;
109    /// body.store(10u32)?;
110    ///
111    /// assert_eq!(body.signature(), "qu");
112    /// body.clear();
113    /// assert_eq!(body.signature(), "");
114    /// # Ok::<_, tokio_dbus::Error>(())
115    /// ```
116    pub fn clear(&mut self) {
117        self.signature.clear();
118        self.buf.clear();
119    }
120
121    /// Get the signature of the buffer.
122    ///
123    /// # Examples
124    ///
125    /// ```
126    /// use tokio_dbus::BodyBuf;
127    ///
128    /// let mut body = BodyBuf::new();
129    ///
130    /// body.store(10u16)?;
131    /// body.store(10u32)?;
132    ///
133    /// assert_eq!(body.signature(), "qu");
134    /// # Ok::<_, tokio_dbus::Error>(())
135    /// ```
136    pub fn signature(&self) -> &Signature {
137        &self.signature
138    }
139
140    /// Get the endianness of the buffer.
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use tokio_dbus::{BodyBuf, Endianness};
146    ///
147    /// let body = BodyBuf::new();
148    /// assert_eq!(body.endianness(), Endianness::NATIVE);
149    ///
150    /// let body = BodyBuf::with_endianness(Endianness::BIG);
151    /// assert_eq!(body.endianness(), Endianness::BIG);
152    /// # Ok::<_, tokio_dbus::Error>(())
153    /// ```
154    pub fn endianness(&self) -> Endianness {
155        self.endianness
156    }
157
158    /// Test if the buffer is empty.
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// use tokio_dbus::{BodyBuf, Endianness};
164    ///
165    /// let mut body = BodyBuf::with_endianness(Endianness::LITTLE);
166    /// assert!(body.is_empty());
167    ///
168    /// body.store(10u16)?;
169    /// body.store(10u32)?;
170    ///
171    /// assert!(!body.is_empty());
172    /// # Ok::<_, tokio_dbus::Error>(())
173    /// ```
174    #[inline]
175    pub fn is_empty(&self) -> bool {
176        self.buf.is_empty()
177    }
178
179    /// Remaining data to be read from the buffer.
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// use tokio_dbus::{BodyBuf, Endianness};
185    ///
186    /// let mut body = BodyBuf::with_endianness(Endianness::LITTLE);
187    /// assert!(body.is_empty());
188    ///
189    /// body.store(10u16)?;
190    /// body.store(10u32)?;
191    ///
192    /// assert_eq!(body.len(), 8);
193    /// # Ok::<_, tokio_dbus::Error>(())
194    /// ```
195    #[inline]
196    pub fn len(&self) -> usize {
197        self.buf.len()
198    }
199
200    /// Align the buffer to the alignment of the given type `T`.
201    #[inline]
202    pub(crate) fn align_mut<T>(&mut self) {
203        self.buf.align_mut::<T>();
204    }
205
206    /// Align the buffer to a dynamically determined alignment.
207    #[inline]
208    pub(crate) fn align_mut_to(&mut self, align: usize) {
209        self.buf.align_mut_to(align);
210    }
211
212    /// Get a slice out of the buffer that has ben written to.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// use tokio_dbus::{BodyBuf, Endianness};
218    ///
219    /// let mut body = BodyBuf::with_endianness(Endianness::LITTLE);
220    ///
221    /// body.store(10u16)?;
222    /// body.store(10u32)?;
223    ///
224    /// assert_eq!(body.signature(), "qu");
225    /// assert_eq!(body.get(), &[10, 0, 0, 0, 10, 0, 0, 0]);
226    /// # Ok::<_, tokio_dbus::Error>(())
227    /// ```
228    #[inline]
229    pub fn get(&self) -> &[u8] {
230        self.buf.get()
231    }
232
233    /// Access a [`Body`] over the entire contents of the buffer.
234    ///
235    /// This is a reader-like abstraction that has a read cursor and endianness,
236    /// allowing convenient read access over the contents of the buffer.
237    ///
238    /// It is also used in combination with [`Message::with_body`] to set the
239    /// message of a body.
240    ///
241    /// [`Message::with_body`]: crate::Message::with_body
242    ///
243    /// # Examples
244    ///
245    /// ```
246    /// use tokio_dbus::{ty, BodyBuf, Endianness};
247    ///
248    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
249    ///
250    /// buf.store_struct::<(u16, u32)>()?
251    ///     .store(20u16)
252    ///     .store(30u32)
253    ///     .finish();
254    ///
255    /// assert_eq!(buf.signature(), "(qu)");
256    ///
257    /// let mut buf = buf.as_body();
258    ///
259    /// let (a, b) = buf.load_struct::<(u16, u32)>()?;
260    /// assert_eq!(a, 20u16);
261    /// assert_eq!(b, 30u32);
262    ///
263    /// assert!(buf.is_empty());
264    /// # Ok::<_, tokio_dbus::Error>(())
265    /// ```
266    #[inline]
267    pub fn as_body(&self) -> Body<'_> {
268        let data = self.buf.as_aligned();
269        Body::from_raw_parts(data, self.endianness, &self.signature)
270    }
271
272    /// Allocate, zero space for and align data for `T`.
273    #[inline]
274    pub(crate) fn alloc<T>(&mut self) -> Alloc<T>
275    where
276        T: Frame,
277    {
278        self.buf.alloc()
279    }
280
281    /// Write the given value at the previously [`Alloc<T>`] position.
282    #[inline]
283    pub(crate) fn store_at<T>(&mut self, at: Alloc<T>, mut frame: T)
284    where
285        T: Frame,
286    {
287        frame.adjust(self.endianness);
288        self.buf.store_at(at, frame);
289    }
290
291    /// Store a [`Frame`] of type `T` in the buffer and add its signature.
292    ///
293    /// This both allocates enough space for the frame and ensures that the
294    /// buffer is aligned per the requirements of the frame.    /// Write a type to the buffer and update the buffer's signature to indicate
295    /// that the type `T` is stored.
296    ///
297    /// # Examples
298    ///
299    /// ```
300    /// use tokio_dbus::{BodyBuf, MessageKind, ObjectPath, SendBuf};
301    ///
302    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
303    ///
304    /// let mut send = SendBuf::new();
305    /// let mut body = BodyBuf::new();
306    ///
307    /// body.store(10f64)?;
308    /// body.store(20u32)?;
309    ///
310    /// let m = send.method_call(PATH, "Hello")
311    ///     .with_body(&body);
312    ///
313    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
314    /// assert_eq!(m.signature(), "du");
315    /// # Ok::<_, tokio_dbus::Error>(())
316    /// ```
317    ///
318    /// Write unsized types:
319    ///
320    /// ```
321    /// use tokio_dbus::{BodyBuf, MessageKind, ObjectPath, SendBuf};
322    ///
323    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
324    ///
325    /// let mut send = SendBuf::new();
326    /// let mut body = BodyBuf::new();
327    ///
328    /// body.store("Hello World!")?;
329    /// body.store(PATH)?;
330    ///
331    /// let m = send.method_call(PATH, "Hello")
332    ///     .with_body(&body);
333    ///
334    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
335    /// assert_eq!(m.signature(), "so");
336    /// # Ok::<_, tokio_dbus::Error>(())
337    /// ```
338    pub fn store<T>(&mut self, frame: T) -> Result<()>
339    where
340        T: Storable,
341    {
342        if !T::write_signature(&mut self.signature) {
343            return Err(SignatureError::too_long().into());
344        }
345
346        frame.store_to(self);
347        Ok(())
348    }
349
350    /// Only store the specified value without appending its signature.
351    pub(crate) fn store_frame<T>(&mut self, mut frame: T)
352    where
353        T: Frame,
354    {
355        frame.adjust(self.endianness);
356        self.buf.store(frame);
357    }
358
359    /// Extend the buffer with a slice.
360    pub(crate) fn extend_from_slice(&mut self, bytes: &[u8]) {
361        self.buf.extend_from_slice(bytes);
362    }
363
364    /// Extend the buffer with a slice ending with a NUL byte.
365    pub(crate) fn extend_from_slice_nul(&mut self, bytes: &[u8]) {
366        self.buf.extend_from_slice_nul(bytes);
367    }
368
369    /// Only write to the buffer without appending a signature.
370    pub(crate) fn write_only<T>(&mut self, value: &T)
371    where
372        T: ?Sized + Write,
373    {
374        value.write_to(self);
375    }
376
377    /// Extend the body with multiple arguments.
378    ///
379    /// This can be a more convenient variant compared with subsequent calls to
380    /// type-dependent calls to [`BodyBuf::store`].
381    ///
382    /// # Examples
383    ///
384    /// ```
385    /// use tokio_dbus::{BodyBuf, MessageKind, ObjectPath, SendBuf};
386    ///
387    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
388    ///
389    /// let mut send = SendBuf::new();
390    /// let mut body = BodyBuf::new();
391    ///
392    /// body.arguments(("Hello World!", PATH, 10u32));
393    ///
394    /// let m = send.method_call(PATH, "Hello")
395    ///     .with_body(&body);
396    ///
397    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
398    /// assert_eq!(m.signature(), "sou");
399    /// # Ok::<_, tokio_dbus::Error>(())
400    /// ```
401    #[inline]
402    pub fn arguments<T>(&mut self, value: T) -> Result<()>
403    where
404        T: Arguments,
405    {
406        value.extend_to(self)
407    }
408
409    /// Write an array into the buffer.
410    ///
411    /// # Examples
412    ///
413    /// ```
414    /// use tokio_dbus::{BodyBuf, Endianness};
415    ///
416    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
417    /// let mut array = buf.store_array::<u32>()?;
418    /// array.store(1u32);
419    /// array.finish();
420    ///
421    /// assert_eq!(buf.signature(), b"au");
422    /// assert_eq!(buf.get(), &[4, 0, 0, 0, 1, 0, 0, 0]);
423    /// # Ok::<_, tokio_dbus::Error>(())
424    /// ```
425    ///
426    /// Writing an empty array still enforces element alignment:
427    ///
428    /// ```
429    /// use tokio_dbus::{BodyBuf, Endianness};
430    ///
431    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
432    /// let mut array = buf.store_array::<u64>()?;
433    /// array.finish();
434    ///
435    /// assert_eq!(buf.signature(), b"at");
436    /// assert_eq!(buf.get(), &[0, 0, 0, 0, 0, 0, 0, 0]);
437    /// # Ok::<_, tokio_dbus::Error>(())
438    /// ```
439    pub fn store_array<E>(&mut self) -> Result<StoreArray<'_, E>>
440    where
441        E: ty::Marker,
442    {
443        <ty::Array<E> as ty::Marker>::write_signature(&mut self.signature)?;
444        // NB: We write directly onto the underlying buffer, because we've
445        // already applied the correct signature.
446        Ok(StoreArray::new(self))
447    }
448
449    /// Write a slice as an byte array.
450    ///
451    /// # Examples
452    ///
453    /// ```
454    /// use tokio_dbus::{BodyBuf, Endianness};
455    ///
456    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
457    /// buf.write_slice(&[1, 2, 3, 4])?;
458    ///
459    /// assert_eq!(buf.signature(), "ay");
460    /// assert_eq!(buf.get(), &[4, 0, 0, 0, 1, 2, 3, 4]);
461    /// # Ok::<_, tokio_dbus::Error>(())
462    /// ```
463    pub fn write_slice(&mut self, data: &[u8]) -> Result<()> {
464        self.store_array::<u8>()?.write_slice(data);
465        Ok(())
466    }
467
468    /// Write a struct into the buffer.
469    ///
470    /// # Examples
471    ///
472    /// ```
473    /// use tokio_dbus::{BodyBuf, Endianness};
474    /// use tokio_dbus::ty;
475    ///
476    /// let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
477    /// buf.store(10u8);
478    ///
479    /// buf.store_struct::<(u16, u32, ty::Array<u8>, ty::Str)>()?
480    ///     .store(10u16)
481    ///     .store(10u32)
482    ///     .store_array(|w| {
483    ///         w.store(1u8);
484    ///         w.store(2u8);
485    ///         w.store(3u8);
486    ///     })
487    ///     .store("Hello World")
488    ///     .finish();
489    ///
490    /// assert_eq!(buf.signature(), b"y(quays)");
491    /// 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]);
492    /// # Ok::<_, tokio_dbus::Error>(())
493    /// ```
494    pub fn store_struct<E>(&mut self) -> Result<StoreStruct<'_, E>>
495    where
496        E: ty::Fields,
497    {
498        E::write_signature(&mut self.signature)?;
499        // NB: We write directly onto the underlying buffer, because we've
500        // already applied the correct signature.
501        Ok(StoreStruct::new(self))
502    }
503
504    /// Write a variant containing a value of the given signature into the
505    /// buffer.
506    ///
507    /// The signature of the contained value is provided at runtime, which is
508    /// what makes it possible to write recursive types.
509    ///
510    /// # Examples
511    ///
512    /// ```
513    /// use tokio_dbus::{BodyBuf, Signature, Variant};
514    ///
515    /// let mut buf = BodyBuf::new();
516    ///
517    /// buf.store_variant(Signature::UINT32)?.store(42u32);
518    ///
519    /// assert_eq!(buf.signature(), Signature::VARIANT);
520    ///
521    /// let mut buf = buf.as_body();
522    /// assert_eq!(buf.read_variant()?, Variant::U32(42));
523    /// # Ok::<_, tokio_dbus::Error>(())
524    /// ```
525    ///
526    /// Containers can be written into the variant as well:
527    ///
528    /// ```
529    /// use tokio_dbus::{ty, BodyBuf, Signature};
530    ///
531    /// let mut buf = BodyBuf::new();
532    ///
533    /// buf.store_variant(Signature::new("(iiay)")?)?
534    ///     .store_struct::<(i32, i32, ty::Array<u8>)>()
535    ///     .store(2i32)
536    ///     .store(2i32)
537    ///     .store_array(|w| w.write_slice(&[0xff; 16]))
538    ///     .finish();
539    ///
540    /// assert_eq!(buf.signature(), Signature::VARIANT);
541    ///
542    /// let mut buf = buf.as_body();
543    /// assert_eq!(buf.skip_variant()?, Signature::new("(iiay)")?);
544    /// assert!(buf.is_empty());
545    /// # Ok::<_, tokio_dbus::Error>(())
546    /// ```
547    pub fn store_variant(&mut self, signature: &Signature) -> Result<StoreVariant<'_>> {
548        if !self.signature.extend_from_signature(Signature::VARIANT) {
549            return Err(SignatureError::too_long().into());
550        }
551
552        Ok(StoreVariant::new(self, signature))
553    }
554
555    /// Extend the signature of the buffer with `signature`, and return a writer
556    /// for a value matching it whose shape does not have to be known when the
557    /// code is written.
558    ///
559    /// This is the entry point used by code which is generic over, or generated
560    /// for, arbitrary D-Bus types. Prefer [`store()`] and the typed container
561    /// writers when the shape of the value is known.
562    ///
563    /// [`store()`]: Self::store
564    ///
565    /// # Examples
566    ///
567    /// ```
568    /// use tokio_dbus::{ty, Alignment, BodyBuf, Signature};
569    ///
570    /// let mut buf = BodyBuf::new();
571    ///
572    /// let mut raw = buf.store_raw(Signature::new("as")?)?;
573    /// let mut array = raw.store_array(Alignment::U32);
574    /// array.as_raw().store("Hello");
575    /// array.as_raw().store("World");
576    /// array.finish();
577    ///
578    /// assert_eq!(buf.signature(), "as");
579    ///
580    /// let mut buf = buf.as_body();
581    /// let mut array = buf.load_array::<ty::Str>()?;
582    /// assert_eq!(array.read()?, Some("Hello"));
583    /// assert_eq!(array.read()?, Some("World"));
584    /// assert_eq!(array.read()?, None);
585    /// # Ok::<_, tokio_dbus::Error>(())
586    /// ```
587    pub fn store_raw(&mut self, signature: &Signature) -> Result<Raw<'_>> {
588        self.extend_signature(signature)?;
589        Ok(Raw::new(self))
590    }
591
592    /// Extend the signature of the buffer without writing anything.
593    ///
594    /// This is used together with [`raw()`] by code which writes several values
595    /// into the same buffer and declares their combined signature up front, such
596    /// as the argument list of a message.
597    ///
598    /// [`raw()`]: Self::raw
599    ///
600    /// # Examples
601    ///
602    /// ```
603    /// use tokio_dbus::{BodyBuf, Signature};
604    ///
605    /// let mut buf = BodyBuf::new();
606    /// buf.extend_signature(Signature::new("us")?)?;
607    ///
608    /// buf.raw().store(42u32);
609    /// buf.raw().store("Hello World!");
610    ///
611    /// assert_eq!(buf.signature(), "us");
612    ///
613    /// let mut buf = buf.as_body();
614    /// assert_eq!(buf.load::<u32>()?, 42);
615    /// assert_eq!(buf.read::<str>()?, "Hello World!");
616    /// # Ok::<_, tokio_dbus::Error>(())
617    /// ```
618    pub fn extend_signature(&mut self, signature: &Signature) -> Result<()> {
619        if !self.signature.extend_from_signature(signature) {
620            return Err(SignatureError::too_long().into());
621        }
622
623        Ok(())
624    }
625
626    /// A writer which writes values without touching the signature of the
627    /// buffer.
628    ///
629    /// See [`extend_signature()`].
630    ///
631    /// [`extend_signature()`]: Self::extend_signature
632    #[inline]
633    pub fn raw(&mut self) -> Raw<'_> {
634        Raw::new(self)
635    }
636}
637
638impl fmt::Debug for BodyBuf {
639    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
640        f.debug_struct("BodyBuf")
641            .field("buf", &self.buf)
642            .field("endianness", &self.endianness)
643            .field("signature", &self.signature.to_signature())
644            .finish()
645    }
646}
647
648impl Default for BodyBuf {
649    #[inline]
650    fn default() -> Self {
651        Self::new()
652    }
653}
654
655/// Construct an aligned buffer from a read buffer.
656impl From<Body<'_>> for BodyBuf {
657    #[inline]
658    fn from(buf: Body<'_>) -> Self {
659        let (buf, endianness, signature) = buf.into_raw_parts();
660        let buf = AlignedBuf::from(buf);
661        let signature = signature.to_owned();
662        Self::from_raw_parts(buf, endianness, signature)
663    }
664}
665
666impl WriteAligned for BodyBuf {
667    /// Only write to the buffer without appending a signature.
668    #[inline]
669    fn write_only<T>(&mut self, value: &T)
670    where
671        T: ?Sized + Write,
672    {
673        BodyBuf::write_only(self, value);
674    }
675
676    #[inline]
677    fn store<T>(&mut self, frame: T) -> Result<()>
678    where
679        T: Storable,
680    {
681        BodyBuf::store(self, frame)
682    }
683
684    #[inline]
685    fn store_frame<T>(&mut self, frame: T)
686    where
687        T: Frame,
688    {
689        BodyBuf::store_frame(self, frame);
690    }
691
692    #[inline]
693    fn extend_from_slice(&mut self, bytes: &[u8]) {
694        BodyBuf::extend_from_slice(self, bytes);
695    }
696
697    #[inline]
698    fn extend_from_slice_nul(&mut self, bytes: &[u8]) {
699        BodyBuf::extend_from_slice_nul(self, bytes);
700    }
701}