dbus_message_parser/message/message_struct.rs
1use crate::{
2 message::{
3 header::{Header, HeaderFields},
4 MessageFlags, MessageType,
5 },
6 value::{Bus, Error, Interface, Member, ObjectPath, Type, TypeError, Value},
7};
8use std::convert::TryInto;
9
10macro_rules! get_field {
11 ($(#[$meta:meta])* $function:ident, $return:ty) => {
12 $(#[$meta])*
13 #[inline]
14 pub const fn $function(&self) -> Option<$return> {
15 self.header.$function()
16 }
17 };
18}
19
20macro_rules! has_field {
21 ($(#[$meta:meta])* $function:ident) => {
22 $(#[$meta])*
23 #[inline]
24 pub const fn $function(&self) -> bool {
25 self.header.$function()
26 }
27 };
28}
29
30/// This represents a DBus [message].
31///
32/// [message]: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol
33#[derive(Debug, Clone, PartialOrd, PartialEq)]
34pub struct Message {
35 pub(crate) header: Header,
36 pub(crate) body: Vec<Value>,
37}
38
39impl Message {
40 /// Create a [`Message`] object.
41 pub fn new(header: Header, body: Vec<Value>) -> Message {
42 Message { header, body }
43 }
44
45 /// Create a [`Message`] object as a [`MethodCall`].
46 ///
47 /// [`MethodCall`]: crate::message::MessageType::MethodCall
48 pub fn method_call(
49 destination: Bus,
50 object_path: ObjectPath,
51 interface: Interface,
52 member: Member,
53 ) -> Message {
54 let fields = HeaderFields {
55 destination: Some(destination),
56 path: Some(object_path),
57 interface: Some(interface),
58 member: Some(member),
59 ..Default::default()
60 };
61
62 let header = Header {
63 is_le: true,
64 message_type: MessageType::MethodCall,
65 message_flags: MessageFlags::empty(),
66 version: 1,
67 serial: 0,
68 fields,
69 };
70 Message {
71 header,
72 body: Vec::new(),
73 }
74 }
75
76 /// Create a [`Message`] object as a [`Signal`].
77 ///
78 /// [`Signal`]: crate::message::MessageType::Signal
79 pub fn signal(object_path: ObjectPath, interface: Interface, member: Member) -> Message {
80 let fields = HeaderFields {
81 path: Some(object_path),
82 interface: Some(interface),
83 member: Some(member),
84 ..Default::default()
85 };
86
87 let header = Header {
88 is_le: true,
89 message_type: MessageType::Signal,
90 message_flags: MessageFlags::NO_REPLY_EXPECTED,
91 version: 1,
92 serial: 0,
93 fields,
94 };
95 Message {
96 header,
97 body: Vec::new(),
98 }
99 }
100
101 /// Create a [`Message`] to retrieve property value.
102 pub fn property_get(
103 destination: Bus,
104 object_path: ObjectPath,
105 interface: Interface,
106 property: &str,
107 ) -> Message {
108 let mut msg = Message::method_call(
109 destination,
110 object_path,
111 "org.freedesktop.DBus.Properties".try_into().unwrap(),
112 "Get".try_into().unwrap(),
113 );
114
115 msg.add_value(Value::String(interface.to_string()));
116 msg.add_value(Value::String(property.to_string()));
117
118 msg
119 }
120
121 /// Create a [`Message`] to retrieve property value.
122 pub fn properties_get_all(
123 destination: Bus,
124 object_path: ObjectPath,
125 interface: Interface,
126 ) -> Message {
127 let mut msg = Message::method_call(
128 destination,
129 object_path,
130 "org.freedesktop.DBus.Properties".try_into().unwrap(),
131 "GetAll".try_into().unwrap(),
132 );
133
134 msg.add_value(Value::String(interface.to_string()));
135
136 msg
137 }
138
139 /// Create a [`Message`] to retrieve property value.
140 pub fn property_set(
141 destination: Bus,
142 object_path: ObjectPath,
143 interface: Interface,
144 property: &str,
145 value: Value,
146 ) -> Message {
147 let mut msg = Message::method_call(
148 destination,
149 object_path,
150 "org.freedesktop.DBus.Properties".try_into().unwrap(),
151 "Set".try_into().unwrap(),
152 );
153
154 msg.add_value(Value::String(interface.to_string()));
155 msg.add_value(Value::String(property.to_string()));
156 msg.add_value(Value::Variant(Box::new(value)));
157
158 msg
159 }
160
161 /// Get the serial number.
162 #[inline]
163 pub const fn get_serial(&self) -> u32 {
164 self.header.get_serial()
165 }
166
167 /// Set the serial number.
168 #[inline]
169 pub fn set_serial(&mut self, serial: u32) {
170 self.header.serial = serial;
171 }
172
173 get_field!(
174 /// Get the [`path`], if there is one in the header field.
175 ///
176 /// [`path`]: crate::message::MessageHeaderFields::path
177 get_path,
178 &ObjectPath
179 );
180
181 has_field!(
182 /// It is true if the message contains a [`path`] in the header fields.
183 ///
184 /// [`path`]: crate::message::MessageHeaderField::path
185 has_path
186 );
187
188 get_field!(
189 /// Get the [`interface`], if there is one in the header field.
190 ///
191 /// [`interface`]: crate::message::MessageHeaderFields::interface
192 get_interface,
193 &Interface
194 );
195
196 has_field!(
197 /// It is true if the message contains an [`interface`] in the header fields.
198 ///
199 /// [`interface`]: crate::message::MessageHeaderFields::interface
200 has_interface
201 );
202
203 get_field!(
204 /// Get the [`member`], if there is one in the header field.
205 ///
206 /// [`member`]: crate::message::MessageHeaderFields::member
207 get_member,
208 &Member
209 );
210
211 has_field!(
212 /// It is true if the message contains a [`member`] in the header fields.
213 ///
214 /// [`member`]: crate::message::MessageHeaderFields::member
215 has_member
216 );
217
218 get_field!(
219 /// Get the [`error_name`], if there is one in the header field.
220 ///
221 /// [`error_name`]: crate::message::MessageHeaderFields::error_name
222 get_error_name,
223 &Error
224 );
225
226 has_field!(
227 /// It is true if the message contains an [`error_name`] in the header fields.
228 ///
229 /// [`error_name`]: crate::message::MessageHeaderFields::error_name
230 has_error_name
231 );
232
233 get_field!(
234 /// Get the [`destination`], if there is one in the header field.
235 ///
236 /// [`destination`]: crate::message::MessageHeaderFields::destination
237 get_destination,
238 &Bus
239 );
240
241 has_field!(
242 /// It is true if the message contains a [`destination`] in the header fields.
243 ///
244 /// [`destination`]: crate::message::MessageHeaderFields::destination
245 has_destination
246 );
247
248 get_field!(
249 /// Get the [`sender`], if there is one in the header field.
250 ///
251 /// [`sender`]: crate::message::MessageHeaderFields::sender
252 get_sender,
253 &Bus
254 );
255
256 has_field!(
257 /// It is true if the message contains a [`sender`] in the header fields.
258 ///
259 /// [`sender`]: crate::message::MessageHeaderFields::sender
260 has_sender
261 );
262
263 get_field!(
264 /// Get the [`reply_serial`], if there is one in the header field.
265 ///
266 /// [`reply_serial`]: crate::message::MessageHeaderFields::reply_serial
267 get_reply_serial,
268 u32
269 );
270
271 has_field!(
272 /// It is true if the message contains a [`reply_serial`] in the header fields.
273 ///
274 /// [`reply_serial`]: crate::message::MessageHeaderFields::reply_serial
275 has_reply_serial
276 );
277
278 /// Get the [`signature`], if there is one in the header field.
279 ///
280 /// [`signature`]: crate::message::MessageHeaderFields::signature
281 pub fn get_signature(&self) -> Result<Vec<Type>, TypeError> {
282 let mut signature = Vec::new();
283 for value in &self.body {
284 let type_ = value.get_type()?;
285 signature.push(type_);
286 }
287
288 Ok(signature)
289 }
290
291 has_field!(
292 /// It is true if the message contains a [`signature`] in the header fields.
293 ///
294 /// [`signature`]: crate::message::MessageHeaderFields::signature
295 has_signature
296 );
297
298 #[cfg(target_family = "unix")]
299 get_field!(
300 /// Get the [`unix_fds`], if there is one in the header field.
301 ///
302 /// [`unix_fds`]: crate::message::MessageHeaderFields::unix_fds
303 get_unix_fds,
304 u32
305 );
306
307 #[cfg(target_family = "unix")]
308 has_field!(
309 /// It is true if the message contains a [`unix_fds`] in the header fields.
310 ///
311 /// [`unix_fds`]: crate::message::MessageHeaderFields::unix_fds
312 has_unix_fds
313 );
314
315 /// Add a new value to the body.
316 pub fn add_value(&mut self, value: Value) {
317 self.body.push(value);
318 }
319
320 /// Create a message return from this [`Message`].
321 /// Only works if this [`Message`] is a [`MethodCall`].
322 ///
323 /// [`MethodCall`]: crate::message::MessageType::MethodCall
324 pub fn method_return(&self) -> Result<Message, Message> {
325 self.header.method_return()
326 }
327
328 /// Create a unknown property error message from this [`Message`].
329 pub fn unknown_property(&self, property: &str) -> Message {
330 self.header.unknown_property(property)
331 }
332
333 /// Create a unknown path error message from this [`Message`].
334 pub fn unknown_path(&self) -> Option<Message> {
335 self.header.unknown_path()
336 }
337
338 /// Create a unknown interface error message from this [`Message`].
339 pub fn unknown_interface(&self) -> Option<Message> {
340 self.header.unknown_interface()
341 }
342
343 /// Create a unknown member error message from this [`Message`].
344 pub fn unknown_member(&self) -> Option<Message> {
345 self.header.unknown_member()
346 }
347
348 /// Create an invalid args error message from this [`Message`].
349 pub fn invalid_args(&self, reason: String) -> Message {
350 self.header.invalid_args(reason)
351 }
352
353 /// Create an error message from this [`Message`].
354 pub fn error(&self, name: Error, message: String) -> Message {
355 self.header.error(name, message)
356 }
357
358 /// Get the body.
359 #[inline]
360 pub fn get_body(&self) -> &[Value] {
361 &self.body
362 }
363
364 /// Get the message type.
365 #[inline]
366 pub fn get_type(&self) -> MessageType {
367 self.header.get_type()
368 }
369
370 /// Split the [`Message`] object into the header and the body.
371 pub fn split(mut self) -> Result<(Header, Vec<Value>), TypeError> {
372 let signature = self.get_signature()?;
373 if !signature.is_empty() {
374 self.header.fields.signature = Some(signature);
375 }
376 Ok((self.header, self.body))
377 }
378}