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}