tokio_dbus/message/
message_buf.rs

1use std::num::NonZeroU32;
2
3use crate::message::OwnedMessageKind;
4use crate::{Body, BodyBuf, Flags, Message, MessageKind, ObjectPath, Signature};
5
6/// An owned D-Bus message.
7///
8/// This is the owned variant of a [`Message`], to convert to a [`Message`], use
9/// [`MessageBuf::borrow`].
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct MessageBuf {
12    /// The type of the message.
13    pub(super) kind: OwnedMessageKind,
14    /// Serial of the emssage.
15    pub(super) serial: NonZeroU32,
16    /// Flags in the message.
17    pub(super) flags: Flags,
18    /// The interface of the message.
19    pub(super) interface: Option<Box<str>>,
20    /// The destination of the message.
21    pub(super) destination: Option<Box<str>>,
22    /// The sender of the message.
23    pub(super) sender: Option<Box<str>>,
24    /// The body associated with the message.
25    pub(super) body: BodyBuf,
26}
27
28impl MessageBuf {
29    /// Construct a method call.
30    ///
31    /// # Examples
32    ///
33    /// ```
34    /// use tokio_dbus::{Message, ObjectPath, MessageBuf, SendBuf};
35    ///
36    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
37    ///
38    /// let mut send = SendBuf::new();
39    ///
40    /// let m = Message::method_call(PATH, "Hello", send.next_serial()).to_owned();
41    /// let m2 = MessageBuf::method_call(PATH.into(), "Hello".into(), m.serial());
42    /// assert_eq!(m, m2);
43    /// ```
44    #[must_use]
45    pub fn method_call(path: Box<ObjectPath>, member: Box<str>, serial: NonZeroU32) -> Self {
46        Self {
47            kind: OwnedMessageKind::MethodCall { path, member },
48            serial,
49            flags: Flags::EMPTY,
50            interface: None,
51            destination: None,
52            sender: None,
53            body: BodyBuf::new(),
54        }
55    }
56
57    /// Convert this message into a [`MessageKind::MethodReturn`] message with
58    /// an empty body where the reply serial matches that of the current
59    /// message.
60    ///
61    /// The `send` argument is used to populate the next serial number.
62    ///
63    /// # Examples
64    ///
65    /// ```
66    /// use tokio_dbus::{Message, MessageKind, ObjectPath, SendBuf};
67    ///
68    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
69    ///
70    /// let mut send = SendBuf::new();
71    ///
72    /// let m = send.method_call(PATH, "Hello")
73    ///     .with_sender("se.tedro.DBusExample")
74    ///     .with_destination("org.freedesktop.DBus")
75    ///     .to_owned();
76    ///
77    /// let m2 = m.clone().method_return(send.next_serial());
78    /// assert!(matches!(m2.kind(), MessageKind::MethodReturn { .. }));
79    ///
80    /// assert_eq!(m.sender(), m2.destination());
81    /// assert_eq!(m.destination(), m2.sender());
82    /// ```
83    #[must_use]
84    pub fn method_return(self, serial: NonZeroU32) -> Self {
85        Self {
86            kind: OwnedMessageKind::MethodReturn {
87                reply_serial: self.serial,
88            },
89            serial,
90            flags: Flags::EMPTY,
91            interface: None,
92            destination: self.sender,
93            sender: self.destination,
94            body: BodyBuf::new(),
95        }
96    }
97
98    /// Construct a signal [`MessageBuf`].
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// use tokio_dbus::{MessageBuf, SendBuf};
104    ///
105    /// let mut send = SendBuf::new();
106    ///
107    /// let m = send.signal("Hello").to_owned();
108    /// let m2 = MessageBuf::signal("Hello".into(), m.serial());
109    /// assert_eq!(m, m2);
110    /// ```
111    #[must_use]
112    pub fn signal(member: Box<str>, serial: NonZeroU32) -> Self {
113        Self {
114            kind: OwnedMessageKind::Signal { member },
115            serial,
116            flags: Flags::EMPTY,
117            interface: None,
118            destination: None,
119            sender: None,
120            body: BodyBuf::new(),
121        }
122    }
123
124    /// Convert this message into a [`MessageKind::Error`] message with
125    /// an empty body where the reply serial matches that of the current
126    /// message.
127    ///
128    /// # Examples
129    ///
130    /// ```
131    /// use tokio_dbus::{Message, MessageKind, ObjectPath, SendBuf};
132    ///
133    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
134    ///
135    /// let mut send = SendBuf::new();
136    ///
137    /// let m = send.method_call(PATH, "Hello")
138    ///     .with_sender("se.tedro.DBusExample")
139    ///     .with_destination("org.freedesktop.DBus");
140    ///
141    /// let m2 = m.clone().error("org.freedesktop.DBus.UnknownMethod", send.next_serial());
142    /// assert!(matches!(m2.kind(), MessageKind::Error { .. }));
143    ///
144    /// assert_eq!(m.sender(), m2.destination());
145    /// assert_eq!(m.destination(), m2.sender());
146    /// ```
147    #[must_use]
148    pub fn error(self, error_name: Box<str>, serial: NonZeroU32) -> Self {
149        Self {
150            kind: OwnedMessageKind::Error {
151                error_name,
152                reply_serial: self.serial,
153            },
154            serial,
155            flags: Flags::EMPTY,
156            interface: None,
157            destination: self.sender,
158            sender: self.destination,
159            body: BodyBuf::new(),
160        }
161    }
162
163    /// Borrow into a [`Message`].
164    #[must_use]
165    pub fn borrow(&self) -> Message<'_> {
166        Message {
167            kind: self.kind.borrow(),
168            serial: self.serial,
169            flags: self.flags,
170            interface: self.interface.as_deref(),
171            destination: self.destination.as_deref(),
172            sender: self.sender.as_deref(),
173            body: self.body.as_body(),
174        }
175    }
176
177    /// Get the kind of the message.
178    ///
179    /// # Examples
180    ///
181    /// ```
182    /// use tokio_dbus::{Message, MessageKind, ObjectPath, SendBuf};
183    ///
184    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
185    ///
186    /// let mut send = SendBuf::new();
187    ///
188    /// let m = send.method_call(PATH, "Hello");
189    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
190    ///
191    /// let m2 = m.error("org.freedesktop.DBus.UnknownMethod", send.next_serial());
192    /// assert!(matches!(m2.kind(), MessageKind::Error { .. }));
193    /// ```
194    #[must_use]
195    pub fn kind(&self) -> MessageKind<'_> {
196        self.kind.borrow()
197    }
198
199    /// Modify the body and signature of the message to match that of the
200    /// provided body buffer.
201    ///
202    /// # Examples
203    ///
204    /// ```
205    /// use tokio_dbus::{BodyBuf, MessageKind, ObjectPath, SendBuf, Signature};
206    ///
207    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
208    ///
209    /// let mut send = SendBuf::new();
210    /// let mut body = BodyBuf::new();
211    ///
212    /// body.store("Hello World!");
213    ///
214    /// let m = send.method_call(PATH, "Hello")
215    ///     .to_owned()
216    ///     .with_body(body);
217    ///
218    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
219    /// assert_eq!(m.signature(), Signature::STRING);
220    /// ```
221    #[must_use]
222    pub fn with_body(self, body: BodyBuf) -> Self {
223        Self { body, ..self }
224    }
225
226    /// Get a buffer to the body of the message.
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// use tokio_dbus::{BodyBuf, MessageKind, ObjectPath, SendBuf};
232    ///
233    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
234    ///
235    /// let mut send = SendBuf::new();
236    /// let mut body = BodyBuf::new();
237    ///
238    /// body.store(42u32);
239    /// body.store("Hello World!");
240    ///
241    /// let m = send.method_call(PATH, "Hello")
242    ///     .to_owned()
243    ///     .with_body(body);
244    ///
245    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
246    /// assert_eq!(m.signature(), "us");
247    ///
248    /// let mut r = m.body();
249    /// assert_eq!(r.load::<u32>()?, 42);
250    /// assert_eq!(r.read::<str>()?, "Hello World!");
251    /// # Ok::<_, tokio_dbus::Error>(())
252    /// ```
253    #[must_use]
254    pub fn body(&self) -> Body<'_> {
255        self.body.as_body()
256    }
257
258    /// Get the serial of the message.
259    ///
260    /// # Examples
261    ///
262    /// ```
263    /// use std::num::NonZeroU32;
264    ///
265    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
266    ///
267    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
268    ///
269    /// let mut send = SendBuf::new();
270    ///
271    /// let m = send.method_call(PATH, "Hello");
272    /// assert_eq!(m.serial().get(), 1);
273    ///
274    /// let m2 = m.with_serial(NonZeroU32::new(1000).unwrap());
275    /// assert_eq!(m2.serial().get(), 1000);
276    /// ```
277    #[must_use]
278    pub fn serial(&self) -> NonZeroU32 {
279        self.serial
280    }
281
282    /// Modify the serial of the message.
283    ///
284    /// # Examples
285    ///
286    /// ```
287    /// use std::num::NonZeroU32;
288    ///
289    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
290    ///
291    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
292    ///
293    /// let mut send = SendBuf::new();
294    ///
295    /// let m = send.method_call(PATH, "Hello");
296    /// assert_eq!(m.serial().get(), 1);
297    ///
298    /// let m2 = m.with_serial(NonZeroU32::new(1000).unwrap());
299    /// assert_eq!(m2.serial().get(), 1000);
300    /// ```
301    #[must_use]
302    pub fn with_serial(self, serial: NonZeroU32) -> Self {
303        Self { serial, ..self }
304    }
305
306    /// Get the flags of the message.
307    ///
308    /// # Examples
309    ///
310    /// ```
311    /// use tokio_dbus::{Flags, Message, ObjectPath, SendBuf};
312    ///
313    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
314    ///
315    /// let mut send = SendBuf::new();
316    ///
317    /// let m = send.method_call(PATH, "Hello");
318    /// assert_eq!(m.flags(), Flags::default());
319    ///
320    /// let m2 = m.with_flags(Flags::NO_REPLY_EXPECTED);
321    /// assert_eq!(m2.flags(), Flags::NO_REPLY_EXPECTED);
322    /// ```
323    #[must_use]
324    pub fn flags(&self) -> Flags {
325        self.flags
326    }
327
328    /// Modify the flags of the message.
329    ///
330    /// # Examples
331    ///
332    /// ```
333    /// use tokio_dbus::{Flags, Message, ObjectPath, SendBuf};
334    ///
335    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
336    ///
337    /// let mut send = SendBuf::new();
338    ///
339    /// let m = send.method_call(PATH, "Hello");
340    /// assert_eq!(m.flags(), Flags::default());
341    ///
342    /// let m2 = m.with_flags(Flags::NO_REPLY_EXPECTED);
343    /// assert_eq!(m2.flags(), Flags::NO_REPLY_EXPECTED);
344    /// ```
345    #[must_use]
346    pub fn with_flags(self, flags: Flags) -> Self {
347        Self { flags, ..self }
348    }
349
350    /// Get the interface of the message.
351    ///
352    /// # Examples
353    ///
354    /// ```
355    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
356    ///
357    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
358    ///
359    /// let mut send = SendBuf::new();
360    ///
361    /// let m = send.method_call(PATH, "Hello").to_owned();
362    /// assert_eq!(m.interface(), None);
363    ///
364    /// let m2 = m.with_interface("org.freedesktop.DBus".into());
365    /// assert_eq!(m2.interface(), Some("org.freedesktop.DBus"));
366    /// ```
367    #[must_use]
368    pub fn interface(&self) -> Option<&str> {
369        self.interface.as_deref()
370    }
371
372    /// Modify the interface of the message.
373    ///
374    /// # Examples
375    ///
376    /// ```
377    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
378    ///
379    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
380    ///
381    /// let mut send = SendBuf::new();
382    ///
383    /// let m = send.method_call(PATH, "Hello").to_owned();
384    /// assert_eq!(m.interface(), None);
385    ///
386    /// let m2 = m.with_interface("org.freedesktop.DBus".into());
387    /// assert_eq!(m2.interface(), Some("org.freedesktop.DBus"));
388    /// ```
389    #[must_use]
390    pub fn with_interface(self, interface: Box<str>) -> Self {
391        Self {
392            interface: Some(interface),
393            ..self
394        }
395    }
396
397    /// Get the destination of the message.
398    ///
399    /// # Examples
400    ///
401    /// ```
402    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
403    ///
404    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
405    ///
406    /// let mut send = SendBuf::new();
407    ///
408    /// let m = send.method_call(PATH, "Hello").to_owned();
409    /// assert_eq!(m.destination(), None);
410    ///
411    /// let m2 = m.with_destination(":1.131".into());
412    /// assert_eq!(m2.destination(), Some(":1.131"));
413    /// ```
414    #[must_use]
415    pub fn destination(&self) -> Option<&str> {
416        self.destination.as_deref()
417    }
418
419    /// Modify the destination of the message.
420    ///
421    /// # Examples
422    ///
423    /// ```
424    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
425    ///
426    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
427    ///
428    /// let mut send = SendBuf::new();
429    ///
430    /// let m = send.method_call(PATH, "Hello").to_owned();
431    /// assert_eq!(m.destination(), None);
432    ///
433    /// let m2 = m.with_destination(":1.131".into());
434    /// assert_eq!(m2.destination(), Some(":1.131"));
435    /// ```
436    #[must_use]
437    pub fn with_destination(self, destination: Box<str>) -> Self {
438        Self {
439            destination: Some(destination),
440            ..self
441        }
442    }
443
444    /// Get the sender of the message.
445    ///
446    /// # Examples
447    ///
448    /// ```
449    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
450    ///
451    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
452    ///
453    /// let mut send = SendBuf::new();
454    ///
455    /// let m = send.method_call(PATH, "Hello").to_owned();
456    /// assert_eq!(m.destination(), None);
457    ///
458    /// let m2 = m.with_sender(":1.131".into());
459    /// assert_eq!(m2.sender(), Some(":1.131"));
460    /// ```
461    #[must_use]
462    pub fn sender(&self) -> Option<&str> {
463        self.sender.as_deref()
464    }
465
466    /// Modify the sender of the message.
467    ///
468    /// # Examples
469    ///
470    /// ```
471    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
472    ///
473    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
474    ///
475    /// let mut send = SendBuf::new();
476    ///
477    /// let m = send.method_call(PATH, "Hello").to_owned();
478    /// assert_eq!(m.destination(), None);
479    ///
480    /// let m2 = m.with_sender(":1.131".into());
481    /// assert_eq!(m2.sender(), Some(":1.131"));
482    /// ```
483    #[must_use]
484    pub fn with_sender(self, sender: Box<str>) -> Self {
485        Self {
486            sender: Some(sender),
487            ..self
488        }
489    }
490
491    /// Get the signature of the message.
492    ///
493    /// # Examples
494    ///
495    /// ```
496    /// use tokio_dbus::{BodyBuf, ObjectPath, SendBuf, Signature};
497    ///
498    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
499    ///
500    /// let mut send = SendBuf::new();
501    ///
502    /// let m = send.method_call(PATH, "Hello").to_owned();
503    /// assert_eq!(m.signature(), Signature::EMPTY);
504    ///
505    /// let mut body = BodyBuf::new();
506    /// body.store("Hello World!");
507    ///
508    /// let m2 = m.with_body(body);
509    /// assert_eq!(m2.signature(), Signature::STRING);
510    /// ```
511    #[must_use]
512    pub fn signature(&self) -> &Signature {
513        self.body.signature()
514    }
515}
516
517impl PartialEq<Message<'_>> for MessageBuf {
518    #[inline]
519    fn eq(&self, other: &Message<'_>) -> bool {
520        *other == *self
521    }
522}