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}