Skip to main content

tokio_dbus/message/
message_buf.rs

1use alloc::boxed::Box;
2
3use crate::message::OwnedMessageKind;
4use crate::{Body, BodyBuf, Flags, Message, MessageKind, ObjectPath, Serial, 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: Serial,
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: Serial) -> 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: Serial) -> 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, ObjectPath, SendBuf};
104    ///
105    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
106    ///
107    /// let mut send = SendBuf::new();
108    ///
109    /// let m = send.signal(PATH, "Hello").to_owned();
110    /// let m2 = MessageBuf::signal(PATH.into(), "Hello".into(), m.serial());
111    /// assert_eq!(m, m2);
112    /// ```
113    #[must_use]
114    pub fn signal(path: Box<ObjectPath>, member: Box<str>, serial: Serial) -> Self {
115        Self {
116            kind: OwnedMessageKind::Signal { path, member },
117            serial,
118            flags: Flags::EMPTY,
119            interface: None,
120            destination: None,
121            sender: None,
122            body: BodyBuf::new(),
123        }
124    }
125
126    /// Convert this message into a [`MessageKind::Error`] message with
127    /// an empty body where the reply serial matches that of the current
128    /// message.
129    ///
130    /// # Examples
131    ///
132    /// ```
133    /// use tokio_dbus::{Message, MessageKind, ObjectPath, SendBuf};
134    ///
135    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
136    ///
137    /// let mut send = SendBuf::new();
138    ///
139    /// let m = send.method_call(PATH, "Hello")
140    ///     .with_sender("se.tedro.DBusExample")
141    ///     .with_destination("org.freedesktop.DBus");
142    ///
143    /// let m2 = m.clone().error("org.freedesktop.DBus.UnknownMethod", send.next_serial());
144    /// assert!(matches!(m2.kind(), MessageKind::Error { .. }));
145    ///
146    /// assert_eq!(m.sender(), m2.destination());
147    /// assert_eq!(m.destination(), m2.sender());
148    /// ```
149    #[must_use]
150    pub fn error(self, error_name: Box<str>, serial: Serial) -> Self {
151        Self {
152            kind: OwnedMessageKind::Error {
153                error_name,
154                reply_serial: self.serial,
155            },
156            serial,
157            flags: Flags::EMPTY,
158            interface: None,
159            destination: self.sender,
160            sender: self.destination,
161            body: BodyBuf::new(),
162        }
163    }
164
165    /// Borrow into a [`Message`].
166    #[must_use]
167    pub fn borrow(&self) -> Message<'_> {
168        Message {
169            kind: self.kind.borrow(),
170            serial: self.serial,
171            flags: self.flags,
172            interface: self.interface.as_deref(),
173            destination: self.destination.as_deref(),
174            sender: self.sender.as_deref(),
175            body: self.body.as_body(),
176        }
177    }
178
179    /// Get the kind of the message.
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// use tokio_dbus::{Message, MessageKind, ObjectPath, SendBuf};
185    ///
186    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
187    ///
188    /// let mut send = SendBuf::new();
189    ///
190    /// let m = send.method_call(PATH, "Hello");
191    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
192    ///
193    /// let m2 = m.error("org.freedesktop.DBus.UnknownMethod", send.next_serial());
194    /// assert!(matches!(m2.kind(), MessageKind::Error { .. }));
195    /// ```
196    #[must_use]
197    pub fn kind(&self) -> MessageKind<'_> {
198        self.kind.borrow()
199    }
200
201    /// Modify the body and signature of the message to match that of the
202    /// provided body buffer.
203    ///
204    /// # Examples
205    ///
206    /// ```
207    /// use tokio_dbus::{BodyBuf, MessageKind, ObjectPath, SendBuf, Signature};
208    ///
209    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
210    ///
211    /// let mut send = SendBuf::new();
212    /// let mut body = BodyBuf::new();
213    ///
214    /// body.store("Hello World!");
215    ///
216    /// let m = send.method_call(PATH, "Hello")
217    ///     .to_owned()
218    ///     .with_body(body);
219    ///
220    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
221    /// assert_eq!(m.signature(), Signature::STRING);
222    /// ```
223    #[must_use]
224    pub fn with_body(self, body: BodyBuf) -> Self {
225        Self { body, ..self }
226    }
227
228    /// Get a buffer to the body of the message.
229    ///
230    /// # Examples
231    ///
232    /// ```
233    /// use tokio_dbus::{BodyBuf, MessageKind, ObjectPath, SendBuf};
234    ///
235    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
236    ///
237    /// let mut send = SendBuf::new();
238    /// let mut body = BodyBuf::new();
239    ///
240    /// body.store(42u32);
241    /// body.store("Hello World!");
242    ///
243    /// let m = send.method_call(PATH, "Hello")
244    ///     .to_owned()
245    ///     .with_body(body);
246    ///
247    /// assert!(matches!(m.kind(), MessageKind::MethodCall { .. }));
248    /// assert_eq!(m.signature(), "us");
249    ///
250    /// let mut r = m.body();
251    /// assert_eq!(r.load::<u32>()?, 42);
252    /// assert_eq!(r.read::<str>()?, "Hello World!");
253    /// # Ok::<_, tokio_dbus::Error>(())
254    /// ```
255    #[must_use]
256    pub fn body(&self) -> Body<'_> {
257        self.body.as_body()
258    }
259
260    /// Get the serial of the message.
261    ///
262    /// # Examples
263    ///
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    /// let initial = m.serial();
273    /// let m2 = m.with_serial(send.next_serial());
274    /// assert_ne!(initial, m2.serial());
275    /// ```
276    #[must_use]
277    pub fn serial(&self) -> Serial {
278        self.serial
279    }
280
281    /// Modify the serial of the message.
282    ///
283    /// # Examples
284    ///
285    /// ```
286    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
287    ///
288    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
289    ///
290    /// let mut send = SendBuf::new();
291    ///
292    /// let m = send.method_call(PATH, "Hello");
293    /// let m2 = send.method_call(PATH, "Hello");
294    /// let m2 = m2.with_serial(m.serial());
295    /// assert_eq!(m.serial(), m2.serial());
296    /// ```
297    #[must_use]
298    pub fn with_serial(self, serial: Serial) -> Self {
299        Self { serial, ..self }
300    }
301
302    /// Get the flags of the message.
303    ///
304    /// # Examples
305    ///
306    /// ```
307    /// use tokio_dbus::{Flags, Message, ObjectPath, SendBuf};
308    ///
309    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
310    ///
311    /// let mut send = SendBuf::new();
312    ///
313    /// let m = send.method_call(PATH, "Hello");
314    /// assert_eq!(m.flags(), Flags::default());
315    ///
316    /// let m2 = m.with_flags(Flags::NO_REPLY_EXPECTED);
317    /// assert_eq!(m2.flags(), Flags::NO_REPLY_EXPECTED);
318    /// ```
319    #[must_use]
320    pub fn flags(&self) -> Flags {
321        self.flags
322    }
323
324    /// Modify the flags of the message.
325    ///
326    /// # Examples
327    ///
328    /// ```
329    /// use tokio_dbus::{Flags, Message, ObjectPath, SendBuf};
330    ///
331    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
332    ///
333    /// let mut send = SendBuf::new();
334    ///
335    /// let m = send.method_call(PATH, "Hello");
336    /// assert_eq!(m.flags(), Flags::default());
337    ///
338    /// let m2 = m.with_flags(Flags::NO_REPLY_EXPECTED);
339    /// assert_eq!(m2.flags(), Flags::NO_REPLY_EXPECTED);
340    /// ```
341    #[must_use]
342    pub fn with_flags(self, flags: Flags) -> Self {
343        Self { flags, ..self }
344    }
345
346    /// Get the interface of the message.
347    ///
348    /// # Examples
349    ///
350    /// ```
351    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
352    ///
353    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
354    ///
355    /// let mut send = SendBuf::new();
356    ///
357    /// let m = send.method_call(PATH, "Hello").to_owned();
358    /// assert_eq!(m.interface(), None);
359    ///
360    /// let m2 = m.with_interface("org.freedesktop.DBus".into());
361    /// assert_eq!(m2.interface(), Some("org.freedesktop.DBus"));
362    /// ```
363    #[must_use]
364    pub fn interface(&self) -> Option<&str> {
365        self.interface.as_deref()
366    }
367
368    /// Modify the interface of the message.
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
374    ///
375    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
376    ///
377    /// let mut send = SendBuf::new();
378    ///
379    /// let m = send.method_call(PATH, "Hello").to_owned();
380    /// assert_eq!(m.interface(), None);
381    ///
382    /// let m2 = m.with_interface("org.freedesktop.DBus".into());
383    /// assert_eq!(m2.interface(), Some("org.freedesktop.DBus"));
384    /// ```
385    #[must_use]
386    pub fn with_interface(self, interface: Box<str>) -> Self {
387        Self {
388            interface: Some(interface),
389            ..self
390        }
391    }
392
393    /// Get the destination of the message.
394    ///
395    /// # Examples
396    ///
397    /// ```
398    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
399    ///
400    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
401    ///
402    /// let mut send = SendBuf::new();
403    ///
404    /// let m = send.method_call(PATH, "Hello").to_owned();
405    /// assert_eq!(m.destination(), None);
406    ///
407    /// let m2 = m.with_destination(":1.131".into());
408    /// assert_eq!(m2.destination(), Some(":1.131"));
409    /// ```
410    #[must_use]
411    pub fn destination(&self) -> Option<&str> {
412        self.destination.as_deref()
413    }
414
415    /// Modify the destination of the message.
416    ///
417    /// # Examples
418    ///
419    /// ```
420    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
421    ///
422    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
423    ///
424    /// let mut send = SendBuf::new();
425    ///
426    /// let m = send.method_call(PATH, "Hello").to_owned();
427    /// assert_eq!(m.destination(), None);
428    ///
429    /// let m2 = m.with_destination(":1.131".into());
430    /// assert_eq!(m2.destination(), Some(":1.131"));
431    /// ```
432    #[must_use]
433    pub fn with_destination(self, destination: Box<str>) -> Self {
434        Self {
435            destination: Some(destination),
436            ..self
437        }
438    }
439
440    /// Get the sender of the message.
441    ///
442    /// # Examples
443    ///
444    /// ```
445    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
446    ///
447    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
448    ///
449    /// let mut send = SendBuf::new();
450    ///
451    /// let m = send.method_call(PATH, "Hello").to_owned();
452    /// assert_eq!(m.destination(), None);
453    ///
454    /// let m2 = m.with_sender(":1.131".into());
455    /// assert_eq!(m2.sender(), Some(":1.131"));
456    /// ```
457    #[must_use]
458    pub fn sender(&self) -> Option<&str> {
459        self.sender.as_deref()
460    }
461
462    /// Modify the sender of the message.
463    ///
464    /// # Examples
465    ///
466    /// ```
467    /// use tokio_dbus::{Message, ObjectPath, SendBuf};
468    ///
469    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
470    ///
471    /// let mut send = SendBuf::new();
472    ///
473    /// let m = send.method_call(PATH, "Hello").to_owned();
474    /// assert_eq!(m.destination(), None);
475    ///
476    /// let m2 = m.with_sender(":1.131".into());
477    /// assert_eq!(m2.sender(), Some(":1.131"));
478    /// ```
479    #[must_use]
480    pub fn with_sender(self, sender: Box<str>) -> Self {
481        Self {
482            sender: Some(sender),
483            ..self
484        }
485    }
486
487    /// Get the signature of the message.
488    ///
489    /// # Examples
490    ///
491    /// ```
492    /// use tokio_dbus::{BodyBuf, ObjectPath, SendBuf, Signature};
493    ///
494    /// const PATH: &ObjectPath = ObjectPath::new_const(b"/org/freedesktop/DBus");
495    ///
496    /// let mut send = SendBuf::new();
497    ///
498    /// let m = send.method_call(PATH, "Hello").to_owned();
499    /// assert_eq!(m.signature(), Signature::EMPTY);
500    ///
501    /// let mut body = BodyBuf::new();
502    /// body.store("Hello World!");
503    ///
504    /// let m2 = m.with_body(body);
505    /// assert_eq!(m2.signature(), Signature::STRING);
506    /// ```
507    #[must_use]
508    pub fn signature(&self) -> &Signature {
509        self.body.signature()
510    }
511}
512
513impl PartialEq<Message<'_>> for MessageBuf {
514    #[inline]
515    fn eq(&self, other: &Message<'_>) -> bool {
516        *other == *self
517    }
518}