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}