1 | //! Contains structs and traits closely related to D-Bus messages. |
2 | |
3 | use std::{fmt, ptr}; |
4 | use super::{ffi, Error, libc, init_dbus}; |
5 | use crate::strings::{BusName, Path, Interface, Member, ErrorName}; |
6 | use std::ffi::CStr; |
7 | |
8 | use super::arg::{Append, AppendAll, IterAppend, ReadAll, Get, Iter, Arg, RefArg, TypeMismatchError}; |
9 | |
10 | #[derive (Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)] |
11 | /// One of the four different message types. |
12 | pub enum MessageType { |
13 | /// This is a method call D-Bus message |
14 | MethodCall = 1, |
15 | /// This is a method return Ok D-Bus message, used when the method call message was successfully processed |
16 | MethodReturn = 2, |
17 | /// This is a method return with error D-Bus message, used when the method call message could not be handled |
18 | Error = 3, |
19 | /// This is a signal, usually sent to whoever wants to listen |
20 | Signal = 4, |
21 | } |
22 | |
23 | impl<'a> TryFrom<&'a str> for MessageType { |
24 | type Error = (); |
25 | |
26 | fn try_from(value: &'a str) -> Result<Self, <crate::message::MessageType as TryFrom<&'a str>>::Error> { |
27 | match value { |
28 | "error" => Ok(MessageType::Error), |
29 | "method_call" => Ok(MessageType::MethodCall), |
30 | "method_return" => Ok(MessageType::MethodReturn), |
31 | "signal" => Ok(MessageType::Signal), |
32 | _ => Err(()) |
33 | } |
34 | } |
35 | } |
36 | |
37 | mod signalargs; |
38 | pub use self::signalargs::SignalArgs; |
39 | |
40 | mod matchrule; |
41 | pub use self::matchrule::MatchRule; |
42 | use std::convert::TryFrom; |
43 | |
44 | mod parser; |
45 | pub use self::parser::Error as MatchRuleParserError; |
46 | |
47 | /// A D-Bus message. A message contains headers - usually destination address, path, interface and member, |
48 | /// and a list of arguments. |
49 | pub struct Message { |
50 | msg: *mut ffi::DBusMessage, |
51 | } |
52 | |
53 | unsafe impl Send for Message {} |
54 | |
55 | impl Message { |
56 | /// Creates a new method call message. |
57 | pub fn new_method_call<'d, 'p, 'i, 'm, D, P, I, M>(destination: D, path: P, iface: I, method: M) -> Result<Message, String> |
58 | where D: Into<BusName<'d>>, P: Into<Path<'p>>, I: Into<Interface<'i>>, M: Into<Member<'m>> { |
59 | init_dbus(); |
60 | let (d, p, i, m) = (destination.into(), path.into(), iface.into(), method.into()); |
61 | let ptr = unsafe { |
62 | ffi::dbus_message_new_method_call(d.as_ptr(), p.as_ptr(), i.as_ptr(), m.as_ptr()) |
63 | }; |
64 | if ptr.is_null() { Err("D-Bus error: dbus_message_new_method_call failed" .into()) } |
65 | else { Ok(Message { msg: ptr}) } |
66 | } |
67 | |
68 | /// Creates a new method call message. |
69 | pub fn method_call(destination: &BusName, path: &Path, iface: &Interface, name: &Member) -> Message { |
70 | init_dbus(); |
71 | let ptr = unsafe { |
72 | ffi::dbus_message_new_method_call(destination.as_ptr(), path.as_ptr(), |
73 | iface.as_ptr(), name.as_ptr()) |
74 | }; |
75 | if ptr.is_null() { panic!("D-Bus error: dbus_message_new_method_call failed" ) } |
76 | Message { msg: ptr} |
77 | } |
78 | |
79 | /// Creates a new message that is a replica of this message, but without a serial. |
80 | /// |
81 | /// May fail if out of memory or file descriptors. |
82 | pub fn duplicate(&self) -> Result<Self, String> { |
83 | let ptr = unsafe { |
84 | ffi::dbus_message_copy(self.msg) |
85 | }; |
86 | if ptr.is_null() { |
87 | Err("D-Bus error: dbus_message_copy failed" .into()) |
88 | } else { |
89 | Ok(Message { msg: ptr }) |
90 | } |
91 | } |
92 | |
93 | /// Creates a new method call message. |
94 | pub fn call_with_args<'d, 'p, 'i, 'm, A, D, P, I, M>(destination: D, path: P, iface: I, method: M, args: A) -> Message |
95 | where D: Into<BusName<'d>>, P: Into<Path<'p>>, I: Into<Interface<'i>>, M: Into<Member<'m>>, A: AppendAll { |
96 | let mut msg = Message::method_call(&destination.into(), &path.into(), &iface.into(), &method.into()); |
97 | msg.append_all(args); |
98 | msg |
99 | } |
100 | |
101 | /// Creates a new signal message. |
102 | pub fn new_signal<P, I, M>(path: P, iface: I, name: M) -> Result<Message, String> |
103 | where P: Into<String>, I: Into<String>, M: Into<String> { |
104 | init_dbus(); |
105 | |
106 | let p = Path::new(path)?; |
107 | let i = Interface::new(iface)?; |
108 | let m = Member::new(name)?; |
109 | |
110 | let ptr = unsafe { |
111 | ffi::dbus_message_new_signal(p.as_ptr(), i.as_ptr(), m.as_ptr()) |
112 | }; |
113 | if ptr.is_null() { Err("D-Bus error: dbus_message_new_signal failed" .into()) } |
114 | else { Ok(Message { msg: ptr}) } |
115 | } |
116 | |
117 | /// Creates a new signal message. |
118 | pub fn signal(path: &Path, iface: &Interface, name: &Member) -> Message { |
119 | init_dbus(); |
120 | let ptr = unsafe { |
121 | ffi::dbus_message_new_signal(path.as_ptr(), iface.as_ptr(), name.as_ptr()) |
122 | }; |
123 | if ptr.is_null() { panic!("D-Bus error: dbus_message_new_signal failed" ) } |
124 | Message { msg: ptr} |
125 | } |
126 | |
127 | /// Creates a method reply for this method call. |
128 | pub fn new_method_return(m: &Message) -> Option<Message> { |
129 | let ptr = unsafe { ffi::dbus_message_new_method_return(m.msg) }; |
130 | if ptr.is_null() { None } else { Some(Message { msg: ptr} ) } |
131 | } |
132 | |
133 | /// Creates a method return (reply) for this method call. |
134 | pub fn method_return(&self) -> Message { |
135 | let ptr = unsafe { ffi::dbus_message_new_method_return(self.msg) }; |
136 | if ptr.is_null() { panic!("D-Bus error: dbus_message_new_method_return failed" ) } |
137 | Message {msg: ptr} |
138 | } |
139 | |
140 | /// Creates a reply for a method call message. |
141 | /// |
142 | /// Panics if called for a message which is not a method call. |
143 | pub fn return_with_args<A: AppendAll>(&self, args: A) -> Message { |
144 | let mut m = self.method_return(); |
145 | m.append_all(args); |
146 | m |
147 | } |
148 | |
149 | /// Creates a new error reply |
150 | pub fn error(&self, error_name: &ErrorName, error_message: &CStr) -> Message { |
151 | let ptr = unsafe { ffi::dbus_message_new_error(self.msg, error_name.as_ptr(), error_message.as_ptr()) }; |
152 | if ptr.is_null() { panic!("D-Bus error: dbus_message_new_error failed" ) } |
153 | Message { msg: ptr} |
154 | } |
155 | |
156 | /// Get the MessageItems that make up the message. |
157 | /// |
158 | /// Note: use `iter_init` or `get1`/`get2`/etc instead for faster access to the arguments. |
159 | /// This method is provided for backwards compatibility. |
160 | pub fn get_items(&self) -> Vec<crate::arg::messageitem::MessageItem> { |
161 | let mut i = self.iter_init(); |
162 | let mut v = vec!(); |
163 | while let Some(z) = crate::arg::messageitem::MessageItem::get(&mut i) { v.push(z); i.next(); } |
164 | v |
165 | } |
166 | |
167 | /// Get the D-Bus serial of a message, if one was specified. |
168 | pub fn get_serial(&self) -> Option<u32> { |
169 | let x = unsafe { ffi::dbus_message_get_serial(self.msg) }; |
170 | if x == 0 { None } else { Some(x) } |
171 | } |
172 | |
173 | /// Get the serial of the message this message is a reply to, if present. |
174 | pub fn get_reply_serial(&self) -> Option<u32> { |
175 | let s = unsafe { ffi::dbus_message_get_reply_serial(self.msg) }; |
176 | if s == 0 { None } else { Some(s) } |
177 | } |
178 | |
179 | /// Returns true if the message does not expect a reply. |
180 | pub fn get_no_reply(&self) -> bool { unsafe { ffi::dbus_message_get_no_reply(self.msg) != 0 } } |
181 | |
182 | /// Set whether or not the message expects a reply. |
183 | /// |
184 | /// Set to true if you send a method call and do not want a reply. |
185 | pub fn set_no_reply(&mut self, v: bool) { |
186 | unsafe { ffi::dbus_message_set_no_reply(self.msg, if v { 1 } else { 0 }) } |
187 | } |
188 | |
189 | /// Returns true if the message can cause a service to be auto-started. |
190 | pub fn get_auto_start(&self) -> bool { unsafe { ffi::dbus_message_get_auto_start(self.msg) != 0 } } |
191 | |
192 | /// Sets whether or not the message can cause a service to be auto-started. |
193 | /// |
194 | /// Defaults to true. |
195 | pub fn set_auto_start(&mut self, v: bool) { |
196 | unsafe { ffi::dbus_message_set_auto_start(self.msg, if v { 1 } else { 0 }) } |
197 | } |
198 | |
199 | /// Add one or more MessageItems to this Message. |
200 | /// |
201 | /// Note: using `append1`, `append2` or `append3` might be faster, especially for large arrays. |
202 | /// This method is provided for backwards compatibility. |
203 | pub fn append_items(&mut self, v: &[crate::arg::messageitem::MessageItem]) { |
204 | let mut ia = IterAppend::new(self); |
205 | for a in v { a.append_by_ref(&mut ia); } |
206 | } |
207 | |
208 | /// Appends one argument to this message. |
209 | /// Use in builder style: e g `m.method_return().append1(7i32)` |
210 | pub fn append1<A: Append>(mut self, a: A) -> Self { |
211 | { |
212 | let mut m = IterAppend::new(&mut self); |
213 | m.append(a); |
214 | } |
215 | self |
216 | } |
217 | |
218 | /// Appends two arguments to this message. |
219 | /// Use in builder style: e g `m.method_return().append2(7i32, 6u8)` |
220 | pub fn append2<A1: Append, A2: Append>(mut self, a1: A1, a2: A2) -> Self { |
221 | { |
222 | let mut m = IterAppend::new(&mut self); |
223 | m.append(a1); m.append(a2); |
224 | } |
225 | self |
226 | } |
227 | |
228 | /// Appends three arguments to this message. |
229 | /// Use in builder style: e g `m.method_return().append3(7i32, 6u8, true)` |
230 | pub fn append3<A1: Append, A2: Append, A3: Append>(mut self, a1: A1, a2: A2, a3: A3) -> Self { |
231 | { |
232 | let mut m = IterAppend::new(&mut self); |
233 | m.append(a1); m.append(a2); m.append(a3); |
234 | } |
235 | self |
236 | } |
237 | |
238 | /// Appends RefArgs to this message. |
239 | /// Use in builder style: e g `m.method_return().append_ref(&[7i32, 6u8, true])` |
240 | pub fn append_ref<A: RefArg>(mut self, r: &[A]) -> Self { |
241 | { |
242 | let mut m = IterAppend::new(&mut self); |
243 | for rr in r { |
244 | rr.append(&mut m); |
245 | } |
246 | } |
247 | self |
248 | } |
249 | |
250 | /// Appends arguments to a message. |
251 | pub fn append_all<A: AppendAll>(&mut self, a: A) { |
252 | let mut m = IterAppend::new(self); |
253 | a.append(&mut m); |
254 | } |
255 | |
256 | /// Gets the first argument from the message, if that argument is of type G1. |
257 | /// Returns None if there are not enough arguments, or if types don't match. |
258 | pub fn get1<'a, G1: Get<'a>>(&'a self) -> Option<G1> { |
259 | let mut i = Iter::new(&self); |
260 | i.get() |
261 | } |
262 | |
263 | /// Gets the first two arguments from the message, if those arguments are of type G1 and G2. |
264 | /// Returns None if there are not enough arguments, or if types don't match. |
265 | pub fn get2<'a, G1: Get<'a>, G2: Get<'a>>(&'a self) -> (Option<G1>, Option<G2>) { |
266 | let mut i = Iter::new(&self); |
267 | let g1 = i.get(); |
268 | if !i.next() { return (g1, None); } |
269 | (g1, i.get()) |
270 | } |
271 | |
272 | /// Gets the first three arguments from the message, if those arguments are of type G1, G2 and G3. |
273 | /// Returns None if there are not enough arguments, or if types don't match. |
274 | pub fn get3<'a, G1: Get<'a>, G2: Get<'a>, G3: Get<'a>>(&'a self) -> (Option<G1>, Option<G2>, Option<G3>) { |
275 | let mut i = Iter::new(&self); |
276 | let g1 = i.get(); |
277 | if !i.next() { return (g1, None, None) } |
278 | let g2 = i.get(); |
279 | if !i.next() { return (g1, g2, None) } |
280 | (g1, g2, i.get()) |
281 | } |
282 | |
283 | /// Gets the first four arguments from the message, if those arguments are of type G1, G2, G3 and G4. |
284 | /// Returns None if there are not enough arguments, or if types don't match. |
285 | pub fn get4<'a, G1: Get<'a>, G2: Get<'a>, G3: Get<'a>, G4: Get<'a>>(&'a self) -> (Option<G1>, Option<G2>, Option<G3>, Option<G4>) { |
286 | let mut i = Iter::new(&self); |
287 | let g1 = i.get(); |
288 | if !i.next() { return (g1, None, None, None) } |
289 | let g2 = i.get(); |
290 | if !i.next() { return (g1, g2, None, None) } |
291 | let g3 = i.get(); |
292 | if !i.next() { return (g1, g2, g3, None) } |
293 | (g1, g2, g3, i.get()) |
294 | } |
295 | |
296 | /// Gets the first five arguments from the message, if those arguments are of type G1, G2, G3 and G4. |
297 | /// Returns None if there are not enough arguments, or if types don't match. |
298 | /// Note: If you need more than five arguments, use `iter_init` instead. |
299 | pub fn get5<'a, G1: Get<'a>, G2: Get<'a>, G3: Get<'a>, G4: Get<'a>, G5: Get<'a>>(&'a self) -> (Option<G1>, Option<G2>, Option<G3>, Option<G4>, Option<G5>) { |
300 | let mut i = Iter::new(&self); |
301 | let g1 = i.get(); |
302 | if !i.next() { return (g1, None, None, None, None) } |
303 | let g2 = i.get(); |
304 | if !i.next() { return (g1, g2, None, None, None) } |
305 | let g3 = i.get(); |
306 | if !i.next() { return (g1, g2, g3, None, None) } |
307 | let g4 = i.get(); |
308 | if !i.next() { return (g1, g2, g3, g4, None) } |
309 | (g1, g2, g3, g4, i.get()) |
310 | } |
311 | |
312 | /// Gets the first argument from the message, if that argument is of type G1. |
313 | /// |
314 | /// Returns a TypeMismatchError if there are not enough arguments, or if types don't match. |
315 | pub fn read1<'a, G1: Arg + Get<'a>>(&'a self) -> Result<G1, TypeMismatchError> { |
316 | let mut i = Iter::new(&self); |
317 | i.read() |
318 | } |
319 | |
320 | /// Gets the first two arguments from the message, if those arguments are of type G1 and G2. |
321 | /// |
322 | /// Returns a TypeMismatchError if there are not enough arguments, or if types don't match. |
323 | pub fn read2<'a, G1: Arg + Get<'a>, G2: Arg + Get<'a>>(&'a self) -> Result<(G1, G2), TypeMismatchError> { |
324 | let mut i = Iter::new(&self); |
325 | Ok((i.read()?, i.read()?)) |
326 | } |
327 | |
328 | /// Gets the first three arguments from the message, if those arguments are of type G1, G2 and G3. |
329 | /// |
330 | /// Returns a TypeMismatchError if there are not enough arguments, or if types don't match. |
331 | pub fn read3<'a, G1: Arg + Get<'a>, G2: Arg + Get<'a>, G3: Arg + Get<'a>>(&'a self) -> |
332 | Result<(G1, G2, G3), TypeMismatchError> { |
333 | let mut i = Iter::new(&self); |
334 | Ok((i.read()?, i.read()?, i.read()?)) |
335 | } |
336 | |
337 | /// Gets the first four arguments from the message, if those arguments are of type G1, G2, G3 and G4. |
338 | /// |
339 | /// Returns a TypeMismatchError if there are not enough arguments, or if types don't match. |
340 | pub fn read4<'a, G1: Arg + Get<'a>, G2: Arg + Get<'a>, G3: Arg + Get<'a>, G4: Arg + Get<'a>>(&'a self) -> |
341 | Result<(G1, G2, G3, G4), TypeMismatchError> { |
342 | let mut i = Iter::new(&self); |
343 | Ok((i.read()?, i.read()?, i.read()?, i.read()?)) |
344 | } |
345 | |
346 | /// Gets the first five arguments from the message, if those arguments are of type G1, G2, G3, G4 and G5. |
347 | /// |
348 | /// Returns a TypeMismatchError if there are not enough arguments, or if types don't match. |
349 | /// Note: If you need more than five arguments, use `iter_init` instead. |
350 | pub fn read5<'a, G1: Arg + Get<'a>, G2: Arg + Get<'a>, G3: Arg + Get<'a>, G4: Arg + Get<'a>, G5: Arg + Get<'a>>(&'a self) -> |
351 | Result<(G1, G2, G3, G4, G5), TypeMismatchError> { |
352 | let mut i = Iter::new(&self); |
353 | Ok((i.read()?, i.read()?, i.read()?, i.read()?, i.read()?)) |
354 | } |
355 | |
356 | /// Gets arguments from a message. |
357 | /// |
358 | /// If this was an error reply or if types mismatch, an error is returned. |
359 | pub fn read_all<R: ReadAll>(&self) -> Result<R, Error> { |
360 | self.set_error_from_msg()?; |
361 | Ok(R::read(&mut self.iter_init())?) |
362 | } |
363 | |
364 | /// Returns a struct for retreiving the arguments from a message. Supersedes get_items(). |
365 | pub fn iter_init(&self) -> Iter { Iter::new(&self) } |
366 | |
367 | /// Gets the MessageType of the Message. |
368 | pub fn msg_type(&self) -> MessageType { |
369 | match unsafe { ffi::dbus_message_get_type(self.msg) } { |
370 | 1 => MessageType::MethodCall, |
371 | 2 => MessageType::MethodReturn, |
372 | 3 => MessageType::Error, |
373 | 4 => MessageType::Signal, |
374 | x => panic!("Invalid message type {}" , x), |
375 | } |
376 | } |
377 | |
378 | fn msg_internal_str<'a>(&'a self, c: *const libc::c_char) -> Option<&'a str> { |
379 | if c.is_null() { return None }; |
380 | let cc = unsafe { CStr::from_ptr(c) }; |
381 | std::str::from_utf8(cc.to_bytes_with_nul()).ok() |
382 | } |
383 | |
384 | /// Gets the name of the connection that originated this message. |
385 | pub fn sender(&self) -> Option<BusName> { |
386 | self.msg_internal_str(unsafe { ffi::dbus_message_get_sender(self.msg) }) |
387 | .map(|s| unsafe { BusName::from_slice_unchecked(s) }) |
388 | } |
389 | |
390 | /// Gets the object path this Message is being sent to. |
391 | pub fn path(&self) -> Option<Path> { |
392 | self.msg_internal_str(unsafe { ffi::dbus_message_get_path(self.msg) }) |
393 | .map(|s| unsafe { Path::from_slice_unchecked(s) }) |
394 | } |
395 | |
396 | /// Gets the destination this Message is being sent to. |
397 | pub fn destination(&self) -> Option<BusName> { |
398 | self.msg_internal_str(unsafe { ffi::dbus_message_get_destination(self.msg) }) |
399 | .map(|s| unsafe { BusName::from_slice_unchecked(s) }) |
400 | } |
401 | |
402 | /// Sets the destination of this Message |
403 | /// |
404 | /// If dest is none, that means broadcast to all relevant destinations. |
405 | pub fn set_destination(&mut self, dest: Option<BusName>) { |
406 | let c_dest = dest.as_ref().map(|d| d.as_cstr().as_ptr()).unwrap_or(ptr::null()); |
407 | assert!(unsafe { ffi::dbus_message_set_destination(self.msg, c_dest) } != 0); |
408 | } |
409 | |
410 | /// Gets the interface this Message is being sent to. |
411 | pub fn interface(&self) -> Option<Interface> { |
412 | self.msg_internal_str(unsafe { ffi::dbus_message_get_interface(self.msg) }) |
413 | .map(|s| unsafe { Interface::from_slice_unchecked(s) }) |
414 | } |
415 | |
416 | /// Gets the interface member being called. |
417 | pub fn member(&self) -> Option<Member> { |
418 | self.msg_internal_str(unsafe { ffi::dbus_message_get_member(self.msg) }) |
419 | .map(|s| unsafe { Member::from_slice_unchecked(s) }) |
420 | } |
421 | |
422 | /// When the remote end returns an error, the message itself is |
423 | /// correct but its contents is an error. This method will |
424 | /// transform such an error to a D-Bus Error or otherwise return |
425 | /// the original message. |
426 | pub fn as_result(&mut self) -> Result<&mut Message, Error> { |
427 | self.set_error_from_msg().map(|_| self) |
428 | } |
429 | |
430 | pub (crate) fn set_error_from_msg(&self) -> Result<(), Error> { |
431 | let mut e = Error::empty(); |
432 | if unsafe { ffi::dbus_set_error_from_message(e.get_mut(), self.msg) } != 0 { Err(e) } |
433 | else { Ok(()) } |
434 | } |
435 | |
436 | pub (crate) fn ptr(&self) -> *mut ffi::DBusMessage { self.msg } |
437 | |
438 | pub (crate) fn from_ptr(ptr: *mut ffi::DBusMessage, add_ref: bool) -> Message { |
439 | if add_ref { |
440 | unsafe { ffi::dbus_message_ref(ptr) }; |
441 | } |
442 | Message { msg: ptr } |
443 | } |
444 | |
445 | /// Sets serial number manually - mostly for internal use |
446 | /// |
447 | /// When sending a message, a serial will be automatically assigned, so you don't need to call |
448 | /// this method. However, it can be very useful in test code that is supposed to handle a method call. |
449 | /// This way, you can create a method call and handle it without sending it to a real D-Bus instance. |
450 | pub fn set_serial(&mut self, val: u32) { |
451 | unsafe { ffi::dbus_message_set_serial(self.msg, val) }; |
452 | } |
453 | |
454 | /// Marshals a message - mostly for internal use |
455 | /// |
456 | /// The function f will be called one or more times with bytes to be written somewhere. |
457 | /// You should call set_serial to manually set a serial number before calling this function |
458 | pub fn marshal<E, F: FnMut(&[u8]) -> Result<(), E>>(&self, mut f: F) -> Result<(), E> { |
459 | let mut len = 0; |
460 | let mut data = ptr::null_mut(); |
461 | if unsafe { ffi::dbus_message_marshal(self.msg, &mut data, &mut len) } == 0 { |
462 | panic!("out of memory" ); |
463 | } |
464 | let s = unsafe { std::slice::from_raw_parts(data as *mut u8 as *const u8, len as usize) }; |
465 | let r = f(s); |
466 | unsafe { ffi::dbus_free(data as *mut _) }; |
467 | r |
468 | } |
469 | |
470 | /// Demarshals a message - mostly for internal use |
471 | pub fn demarshal(data: &[u8]) -> Result<Self, Error> { |
472 | let mut e = Error::empty(); |
473 | let p = unsafe { ffi::dbus_message_demarshal(data.as_ptr() as *const _, data.len() as _, e.get_mut()) }; |
474 | if p == ptr::null_mut() { |
475 | Err(e) |
476 | } else { |
477 | Ok(Self::from_ptr(p, false)) |
478 | } |
479 | } |
480 | |
481 | /// Returns the size of the message - mostly for internal use |
482 | /// |
483 | /// Returns Err(()) on protocol errors. Make sure you have at least 16 bytes in the buffer |
484 | /// before calling this method. |
485 | pub fn demarshal_bytes_needed(data: &[u8]) -> Result<usize, ()> { |
486 | const MIN_HEADER: usize = 16; |
487 | if data.len() < MIN_HEADER { return Ok(MIN_HEADER); } |
488 | let x = unsafe { ffi::dbus_message_demarshal_bytes_needed(data.as_ptr() as *const _, data.len() as _) }; |
489 | if x < MIN_HEADER as _ { Err(()) } else { Ok(x as usize) } |
490 | } |
491 | |
492 | } |
493 | |
494 | impl Drop for Message { |
495 | fn drop(&mut self) { |
496 | unsafe { |
497 | ffi::dbus_message_unref(self.msg); |
498 | } |
499 | } |
500 | } |
501 | |
502 | impl fmt::Debug for Message { |
503 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
504 | let mut x: DebugStruct<'_, '_> = f.debug_struct(name:"Message" ); |
505 | x.field(name:"Type" , &self.msg_type()); |
506 | // The &&** derefs to a &&str, which implements &dyn Debug |
507 | if let Some(ref path: &Path<'_>) = self.path() { x.field(name:"Path" , &&**path); } |
508 | if let Some(ref iface: &Interface<'_>) = self.interface() { x.field(name:"Interface" , &&**iface); } |
509 | if let Some(ref member: &Member<'_>) = self.member() { x.field(name:"Member" , &&**member); } |
510 | if let Some(ref sender: &BusName<'_>) = self.sender() { x.field(name:"Sender" , &&**sender); } |
511 | if let Some(ref dest: &BusName<'_>) = self.destination() { x.field(name:"Destination" , &&**dest); } |
512 | if let Some(ref serial: &u32) = self.get_serial() { x.field(name:"Serial" , value:serial); } |
513 | if let Some(ref rs: &u32) = self.get_reply_serial() { x.field(name:"ReplySerial" , value:rs); } |
514 | let mut args: Vec> = vec!(); |
515 | let mut iter: Iter<'_> = self.iter_init(); |
516 | while let Some(a: Box) = iter.get_refarg() { |
517 | args.push(a); |
518 | iter.next(); |
519 | } |
520 | let args2: &[_] = &args; |
521 | x.field(name:"Args" , &args2); |
522 | x.finish() |
523 | } |
524 | } |
525 | |
526 | #[cfg (test)] |
527 | mod test { |
528 | use crate::{Message}; |
529 | use crate::strings::BusName; |
530 | |
531 | #[test ] |
532 | fn set_valid_destination() { |
533 | let mut m = Message::new_method_call("org.test.rust" , "/" , "org.test.rust" , "Test" ).unwrap(); |
534 | let d = Some(BusName::new(":1.14" ).unwrap()); |
535 | m.set_destination(d); |
536 | |
537 | assert!(!m.get_no_reply()); |
538 | m.set_no_reply(true); |
539 | assert!(m.get_no_reply()); |
540 | } |
541 | |
542 | #[test ] |
543 | fn marshal() { |
544 | let mut m = Message::new_method_call("org.freedesktop.DBus" , "/org/freedesktop/DBus" , "org.freedesktop.DBus" , "Hello" ).unwrap(); |
545 | m.set_serial(1); |
546 | let r = m.marshal(|d| { |
547 | let m2 = Message::demarshal(d).unwrap(); |
548 | assert_eq!(&*m2.path().unwrap(), "/org/freedesktop/DBus" ); |
549 | Err(45) |
550 | }); |
551 | assert_eq!(45, r.unwrap_err()); |
552 | } |
553 | } |
554 | |