Coverage Report

Created: 2024-04-26 06:25

/rust/registry/src/index.crates.io-6f17d22bba15001f/dbus-0.9.7/src/arg/messageitem.rs
Line
Count
Source (jump to first uncovered line)
1
//! MessageItem - old, enum design that is used as parameters and return values from
2
//! method calls, or as data added to a signal.
3
//!
4
//! Note that the newer generic design (see `arg` module) is, in general, both faster
5
//! and smaller than MessageItem, and should be your first hand choice
6
//! whenever applicable. There is also a trait object design called `RefArg` in
7
//! case the generic design is too inflexible.
8
9
use crate::strings::{Signature, Path, Interface, BusName};
10
11
use crate::arg;
12
use crate::arg::{Iter, IterAppend, Arg, ArgType};
13
use crate::arg::OwnedFd;
14
use std::ffi::CStr;
15
use std::{ops, any};
16
17
use crate::{ffidisp::Connection, Message, Error};
18
use std::collections::BTreeMap;
19
use std::convert::TryFrom;
20
21
0
#[derive(Debug,Copy,Clone)]
22
/// Errors that can happen when creating a MessageItem::Array.
23
pub enum ArrayError {
24
    /// The array is empty.
25
    EmptyArray,
26
    /// The array is composed of different element types.
27
    DifferentElementTypes,
28
    /// The supplied signature is not a valid array signature
29
    InvalidSignature,
30
}
31
32
33
/// OwnedFd wrapper for MessageItem
34
#[cfg(feature = "stdfd")]
35
#[derive(Debug)]
36
pub struct MessageItemFd(pub OwnedFd);
37
38
#[cfg(feature = "stdfd")]
39
mod messageitem_fd_impl {
40
    use super::*;
41
    impl Clone for MessageItemFd {
42
        fn clone(&self) -> Self { MessageItemFd(self.0.try_clone().unwrap()) }
43
    }
44
45
    impl PartialEq for MessageItemFd {
46
        fn eq(&self, _rhs: &Self) -> bool { false }
47
    }
48
49
    impl PartialOrd for MessageItemFd {
50
        fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
51
            use std::os::fd::AsRawFd;
52
            let a = self.0.as_raw_fd();
53
            let b = other.0.as_raw_fd();
54
            a.partial_cmp(&b)
55
        }
56
    }
57
58
    impl From<OwnedFd> for MessageItem { fn from(i: OwnedFd) -> MessageItem { MessageItem::UnixFd(MessageItemFd(i)) } }
59
60
    impl<'a> TryFrom<&'a MessageItem> for &'a OwnedFd {
61
        type Error = ();
62
        fn try_from(i: &'a MessageItem) -> Result<&'a OwnedFd,()> { if let MessageItem::UnixFd(ref b) = i { Ok(&b.0) } else { Err(()) } }
63
    }
64
}
65
66
0
#[derive(Debug, Clone, PartialEq, PartialOrd)]
67
/// An array of MessageItem where every MessageItem is of the same type.
68
pub struct MessageItemArray {
69
    v: Vec<MessageItem>,
70
    // signature includes the "a"!
71
    sig: Signature<'static>,
72
}
73
74
impl MessageItemArray {
75
    /// Creates a new array where every element has the supplied signature.
76
    ///
77
    /// Signature is the full array signature, not the signature of the element.
78
0
    pub fn new(v: Vec<MessageItem>, sig: Signature<'static>) -> Result<MessageItemArray, ArrayError> {
79
0
        let a = MessageItemArray {v: v, sig: sig };
80
0
        if a.sig.as_bytes()[0] != ffi::DBUS_TYPE_ARRAY as u8 { return Err(ArrayError::InvalidSignature) }
81
0
        {
82
0
            let esig = a.element_signature();
83
0
            for i in &a.v {
84
0
                if i.signature().as_cstr() != esig { return Err(ArrayError::DifferentElementTypes) }
85
            }
86
        }
87
0
        Ok(a)
88
0
    }
89
90
0
    fn element_signature(&self) -> &CStr {
91
0
        let z = &self.sig.as_cstr().to_bytes_with_nul()[1..];
92
0
        unsafe { CStr::from_bytes_with_nul_unchecked(z) }
93
0
    }
94
95
0
    fn make_sig(m: &MessageItem) -> Signature<'static> {
96
0
        Signature::new(format!("a{}", m.signature())).unwrap()
97
0
    }
98
99
    /// Signature of array (full array signature)
100
0
    pub fn signature(&self) -> &Signature<'static> { &self.sig }
101
102
    /// Consumes the MessageItemArray in order to allow you to modify the individual items of the array.
103
0
    pub fn into_vec(self) -> Vec<MessageItem> { self.v }
104
}
105
106
impl ops::Deref for MessageItemArray {
107
    type Target = [MessageItem];
108
0
    fn deref(&self) -> &Self::Target { &self.v }
109
}
110
111
impl arg::Append for MessageItemArray {
112
0
    fn append_by_ref(&self, i: &mut IterAppend) {
113
0
        i.append_container(ArgType::Array, Some(self.element_signature()), |s| {
114
0
            for a in &self.v { a.append_by_ref(s) }
115
0
        });
116
0
    }
117
}
118
119
0
#[derive(Debug, Clone, PartialEq, PartialOrd)]
120
/// An array of MessageItem where every MessageItem is of the same type.
121
pub struct MessageItemDict {
122
    v: Vec<(MessageItem, MessageItem)>,
123
    // signature includes the "a"!
124
    sig: Signature<'static>,
125
}
126
127
impl MessageItemDict {
128
    /// Creates a new dict where every key and value elements have the supplied signature.
129
0
    pub fn new(v: Vec<(MessageItem, MessageItem)>, keysig: Signature<'static>, valuesig: Signature<'static>) -> Result<MessageItemDict, ArrayError> {
130
0
        let sig = Signature::from(format!("a{{{}{}}}", keysig, valuesig));
131
0
        let a = MessageItemDict {v: v, sig: sig };
132
0
        for (k, v) in &a.v {
133
0
            if keysig != k.signature() || valuesig != v.signature() {
134
0
                return Err(ArrayError::DifferentElementTypes);
135
0
            }
136
        }
137
0
        Ok(a)
138
0
    }
139
140
0
    fn element_signature(&self) -> &CStr {
141
0
        let z = &self.sig.as_cstr().to_bytes_with_nul()[1..];
142
0
        unsafe { CStr::from_bytes_with_nul_unchecked(z) }
143
0
    }
144
145
    /// Signature of array (full array signature)
146
0
    pub fn signature(&self) -> &Signature<'static> { &self.sig }
147
148
    /// Consumes the MessageItemDict in order to allow you to modify the individual items of the dict.
149
0
    pub fn into_vec(self) -> Vec<(MessageItem, MessageItem)> { self.v }
150
}
151
152
impl ops::Deref for MessageItemDict {
153
    type Target = [(MessageItem, MessageItem)];
154
0
    fn deref(&self) -> &Self::Target { &self.v }
155
}
156
157
impl arg::Append for MessageItemDict {
158
0
    fn append_by_ref(&self, i: &mut IterAppend) {
159
0
        i.append_container(ArgType::Array, Some(self.element_signature()), |s| {
160
0
            for (k, v) in &self.v {
161
0
                s.append_container(ArgType::DictEntry, None, |ss| {
162
0
                    k.append_by_ref(ss);
163
0
                    v.append_by_ref(ss);
164
0
                });
165
0
            }
166
0
        });
167
0
    }
168
}
169
170
/// MessageItem - used as parameters and return values from
171
/// method calls, or as data added to a signal (old, enum version).
172
///
173
/// Note that the newer generic design (see `arg` module) is both faster
174
/// and less error prone than MessageItem, and should be your first hand choice
175
/// whenever applicable.
176
0
#[derive(Debug, PartialEq, PartialOrd, Clone)]
177
pub enum MessageItem {
178
    /// A D-Bus array requires all elements to be of the same type.
179
    /// All elements must match the Signature.
180
    Array(MessageItemArray),
181
    /// A D-Bus struct allows for values of different types.
182
    Struct(Vec<MessageItem>),
183
    /// A D-Bus variant is a wrapper around another `MessageItem`, which
184
    /// can be of any type.
185
    Variant(Box<MessageItem>),
186
    /// A D-Bus dictionary. All keys and values are required to be of the same type.
187
    /// Not all types can be dictionary keys, but all can be dictionary values.
188
    Dict(MessageItemDict),
189
    /// A D-Bus objectpath requires its content to be a valid objectpath,
190
    /// so this cannot be any string.
191
    ObjectPath(Path<'static>),
192
    /// A D-Bus signature requires its content to be a valid type signature,
193
    /// so this cannot be any string.
194
    Signature(Signature<'static>),
195
    /// A D-Bus String is zero terminated, so no \0 s in the String, please.
196
    /// (D-Bus strings are also - like Rust strings - required to be valid UTF-8.)
197
    Str(String),
198
    /// A D-Bus boolean type.
199
    Bool(bool),
200
    /// A D-Bus unsigned 8 bit type.
201
    Byte(u8),
202
    /// A D-Bus signed 16 bit type.
203
    Int16(i16),
204
    /// A D-Bus signed 32 bit type.
205
    Int32(i32),
206
    /// A D-Bus signed 64 bit type.
207
    Int64(i64),
208
    /// A D-Bus unsigned 16 bit type.
209
    UInt16(u16),
210
    /// A D-Bus unsigned 32 bit type.
211
    UInt32(u32),
212
    /// A D-Bus unsigned 64 bit type.
213
    UInt64(u64),
214
    /// A D-Bus IEEE-754 double-precision floating point type.
215
    Double(f64),
216
    /// D-Bus allows for sending file descriptors, which can be used to
217
    /// set up SHM, unix pipes, or other communication channels.
218
    #[cfg(not(feature = "stdfd"))]
219
    UnixFd(OwnedFd),
220
    /// D-Bus allows for sending file descriptors, which can be used to
221
    /// set up SHM, unix pipes, or other communication channels.
222
    #[cfg(feature = "stdfd")]
223
    UnixFd(MessageItemFd),
224
}
225
226
impl MessageItem {
227
    /// Get the D-Bus Signature for this MessageItem.
228
0
    pub fn signature(&self) -> Signature<'static> {
229
0
        use crate::arg::Variant;
230
0
        match self {
231
0
            MessageItem::Str(_) => <String as Arg>::signature(),
232
0
            MessageItem::Bool(_) => <bool as Arg>::signature(),
233
0
            MessageItem::Byte(_) => <u8 as Arg>::signature(),
234
0
            MessageItem::Int16(_) => <i16 as Arg>::signature(),
235
0
            MessageItem::Int32(_) => <i32 as Arg>::signature(),
236
0
            MessageItem::Int64(_) => <i64 as Arg>::signature(),
237
0
            MessageItem::UInt16(_) => <u16 as Arg>::signature(),
238
0
            MessageItem::UInt32(_) => <u32 as Arg>::signature(),
239
0
            MessageItem::UInt64(_) => <u64 as Arg>::signature(),
240
0
            MessageItem::Double(_) => <f64 as Arg>::signature(),
241
0
            MessageItem::Array(ref a) => a.sig.clone(),
242
0
            MessageItem::Struct(ref s) => Signature::new(format!("({})", s.iter().fold(String::new(), |s, i| s + &*i.signature()))).unwrap(),
243
0
            MessageItem::Variant(_) => <Variant<u8> as Arg>::signature(),
244
0
            MessageItem::Dict(ref a) => a.sig.clone(),
245
0
            MessageItem::ObjectPath(_) => <Path as Arg>::signature(),
246
0
            MessageItem::Signature(_) => <Signature as Arg>::signature(),
247
0
            MessageItem::UnixFd(_) => <std::fs::File as Arg>::signature(),
248
        }
249
0
    }
250
251
    /// Get the arg type of this MessageItem.
252
0
    pub fn arg_type(&self) -> arg::ArgType {
253
0
        match self {
254
0
            MessageItem::Str(_) => ArgType::String,
255
0
            MessageItem::Bool(_) => ArgType::Boolean,
256
0
            MessageItem::Byte(_) => ArgType::Byte,
257
0
            MessageItem::Int16(_) => ArgType::Int16,
258
0
            MessageItem::Int32(_) => ArgType::Int32,
259
0
            MessageItem::Int64(_) => ArgType::Int64,
260
0
            MessageItem::UInt16(_) => ArgType::UInt16,
261
0
            MessageItem::UInt32(_) => ArgType::UInt32,
262
0
            MessageItem::UInt64(_) => ArgType::UInt64,
263
0
            MessageItem::Double(_) => ArgType::Double,
264
0
            MessageItem::Array(_) => ArgType::Array,
265
0
            MessageItem::Struct(_) => ArgType::Struct,
266
0
            MessageItem::Variant(_) => ArgType::Variant,
267
0
            MessageItem::Dict(_) => ArgType::Array,
268
0
            MessageItem::ObjectPath(_) => ArgType::ObjectPath,
269
0
            MessageItem::Signature(_) => ArgType::Signature,
270
0
            MessageItem::UnixFd(_) => ArgType::UnixFd,
271
        }
272
0
    }
273
274
    /// Creates a (String, Variant) dictionary from an iterator with Result passthrough (an Err will abort and return that Err)
275
0
    pub fn from_dict<E, I: Iterator<Item=Result<(String, MessageItem),E>>>(i: I) -> Result<MessageItem, E> {
276
0
        let mut v = Vec::new();
277
0
        for r in i {
278
0
            let (s, vv) = r?;
279
0
            v.push((s.into(), Box::new(vv).into()));
280
        }
281
0
        Ok(MessageItem::Dict(MessageItemDict::new(v, Signature::new("s").unwrap(), Signature::new("v").unwrap()).unwrap()))
282
0
    }
283
284
    /// Creates an MessageItem::Array from a list of MessageItems.
285
    ///
286
    /// Note: This requires `v` to be non-empty. See also
287
    /// `MessageItem::from(&[T])`, which can handle empty arrays as well.
288
0
    pub fn new_array(v: Vec<MessageItem>) -> Result<MessageItem, ArrayError> {
289
0
        if v.is_empty() {
290
0
            return Err(ArrayError::EmptyArray);
291
0
        }
292
0
        let s = MessageItemArray::make_sig(&v[0]);
293
0
        Ok(MessageItem::Array(MessageItemArray::new(v, s)?))
294
0
    }
295
296
    /// Creates an MessageItem::Dict from a list of MessageItem pairs.
297
    ///
298
    /// Note: This requires `v` to be non-empty. See also
299
    /// `MessageItem::from(&[(T1, T2)])`, which can handle empty arrays as well.
300
0
    pub fn new_dict(v: Vec<(MessageItem, MessageItem)>) -> Result<MessageItem, ArrayError> {
301
0
        if v.is_empty() {
302
0
            return Err(ArrayError::EmptyArray);
303
0
        }
304
0
        let (s1, s2) = (v[0].0.signature(), v[0].1.signature());
305
0
        Ok(MessageItem::Dict(MessageItemDict::new(v, s1, s2)?))
306
0
    }
307
308
    /// Get the inner value of a `MessageItem`
309
    ///
310
    /// # Example
311
    /// ```
312
    /// use dbus::arg::messageitem::MessageItem;
313
    /// let m: MessageItem = 5i64.into();
314
    /// let s: i64 = m.inner().unwrap();
315
    /// assert_eq!(s, 5i64);
316
    /// ```
317
0
    pub fn inner<'a, T: TryFrom<&'a MessageItem>>(&'a self) -> Result<T, T::Error> {
318
0
        T::try_from(self)
319
0
    }
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem>::inner::<&alloc::vec::Vec<dbus::arg::messageitem::MessageItem>>
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem>::inner::<&[(dbus::arg::messageitem::MessageItem, dbus::arg::messageitem::MessageItem)]>
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem>::inner::<&alloc::string::String>
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem>::inner::<&alloc::boxed::Box<dbus::arg::messageitem::MessageItem>>
320
321
    /// Get the underlying `MessageItem` of a `MessageItem::Variant`
322
    ///
323
    /// Nested `MessageItem::Variant`s are unwrapped recursively until a
324
    /// non-`Variant` is found.
325
    ///
326
    /// # Example
327
    /// ```
328
    /// use dbus::arg::messageitem::MessageItem;
329
    /// let nested = MessageItem::Variant(Box::new(6i64.into()));
330
    /// let flat: MessageItem = 6i64.into();
331
    /// assert_ne!(&nested, &flat);
332
    /// assert_eq!(nested.peel(), &flat);
333
    /// ```
334
0
    pub fn peel(&self) -> &Self {
335
0
        let mut current = self;
336
337
0
        while let MessageItem::Variant(b) = current {
338
0
            current = &*b;
339
0
        }
340
341
0
        current
342
0
    }
343
344
0
    fn new_array2<D, I>(i: I) -> MessageItem
345
0
    where D: Into<MessageItem>, D: Default, I: Iterator<Item=D> {
346
0
        let v: Vec<MessageItem> = i.map(|ii| ii.into()).collect();
347
0
        let s = {
348
0
            let d;
349
0
            let t = if v.is_empty() { d = D::default().into(); &d } else { &v[0] };
350
0
            MessageItemArray::make_sig(t)
351
0
        };
352
0
        MessageItem::Array(MessageItemArray::new(v, s).unwrap())
353
0
    }
354
355
0
    fn new_dict2<K, V, I>(i: I) -> MessageItem
356
0
    where K: Into<MessageItem> + Default, V: Into<MessageItem> + Default, I: Iterator<Item=(K, V)> {
357
0
        let v: Vec<(MessageItem, MessageItem)> = i.map(|(k, v)| (k.into(), v.into())).collect();
358
0
        let (kt, vt) = if v.is_empty() {
359
0
            let kd = K::default().into();
360
0
            let vd = V::default().into();
361
0
            (kd.signature(), vd.signature())
362
0
        } else { (v[0].0.signature(), v[0].1.signature()) };
363
0
        MessageItem::Dict(MessageItemDict::new(v, kt, vt).unwrap())
364
0
    }
365
}
366
367
macro_rules! msgitem_convert {
368
    ($t: ty, $s: ident) => {
369
0
        impl From<$t> for MessageItem { fn from(i: $t) -> MessageItem { MessageItem::$s(i) } }
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<i64>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<u32>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<i16>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<u64>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<f64>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<u16>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<u8>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<i32>>::from
Unexecuted instantiation: <dbus::arg::messageitem::MessageItem as core::convert::From<bool>>::from
370
371
        impl<'a> TryFrom<&'a MessageItem> for $t {
372
            type Error = ();
373
0
            fn try_from(i: &'a MessageItem) -> Result<$t,()> {
374
0
                if let MessageItem::$s(b) = i.peel() { Ok(*b) } else { Err(()) }
375
0
            }
Unexecuted instantiation: <i16 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <u16 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <bool as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <u64 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <i32 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <f64 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <u32 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <i64 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
Unexecuted instantiation: <u8 as core::convert::TryFrom<&dbus::arg::messageitem::MessageItem>>::try_from
376
        }
377
    }
378
}
379
380
msgitem_convert!(u8, Byte);
381
msgitem_convert!(u64, UInt64);
382
msgitem_convert!(u32, UInt32);
383
msgitem_convert!(u16, UInt16);
384
msgitem_convert!(i16, Int16);
385
msgitem_convert!(i32, Int32);
386
msgitem_convert!(i64, Int64);
387
msgitem_convert!(f64, Double);
388
msgitem_convert!(bool, Bool);
389
390
391
392
/// Create a `MessageItem::Array`.
393
impl<'a, T> From<&'a [T]> for MessageItem
394
where T: Into<MessageItem> + Clone + Default {
395
0
    fn from(i: &'a [T]) -> MessageItem {
396
0
        MessageItem::new_array2(i.iter().cloned())
397
0
    }
398
}
399
400
/// Create a `MessageItem::Dict`.
401
impl<'a, T1, T2> From<&'a [(T1, T2)]> for MessageItem
402
where T1: Into<MessageItem> + Clone + Default, T2: Into<MessageItem> + Clone + Default {
403
0
    fn from(i: &'a [(T1, T2)]) -> MessageItem {
404
0
        MessageItem::new_dict2(i.iter().cloned())
405
0
    }
406
}
407
408
0
impl<'a> From<&'a str> for MessageItem { fn from(i: &str) -> MessageItem { MessageItem::Str(i.to_string()) } }
409
410
0
impl From<String> for MessageItem { fn from(i: String) -> MessageItem { MessageItem::Str(i) } }
411
412
0
impl From<Path<'static>> for MessageItem { fn from(i: Path<'static>) -> MessageItem { MessageItem::ObjectPath(i) } }
413
414
0
impl From<Signature<'static>> for MessageItem { fn from(i: Signature<'static>) -> MessageItem { MessageItem::Signature(i) } }
415
416
#[cfg(not(feature = "stdfd"))]
417
0
impl From<OwnedFd> for MessageItem { fn from(i: OwnedFd) -> MessageItem { MessageItem::UnixFd(i) } }
418
419
#[cfg(unix)]
420
impl From<std::fs::File> for MessageItem {
421
0
    fn from(i: std::fs::File) -> MessageItem {
422
0
        use std::os::unix::io::{FromRawFd, IntoRawFd};
423
0
        let fd = unsafe { OwnedFd::from_raw_fd(i.into_raw_fd()) };
424
0
        fd.into()
425
0
    }
426
}
427
428
/// Create a `MessageItem::Variant`
429
impl From<Box<MessageItem>> for MessageItem {
430
0
    fn from(i: Box<MessageItem>) -> MessageItem { MessageItem::Variant(i) }
431
}
432
433
impl<'a> TryFrom<&'a MessageItem> for &'a str {
434
    type Error = ();
435
0
    fn try_from(i: &'a MessageItem) -> Result<&'a str, Self::Error> {
436
0
        match i.peel() {
437
0
            MessageItem::Str(ref b) => Ok(b),
438
0
            MessageItem::ObjectPath(ref b) => Ok(b),
439
0
            MessageItem::Signature(ref b) => Ok(b),
440
0
            _ => Err(()),
441
        }
442
0
    }
443
}
444
445
impl<'a> TryFrom<&'a MessageItem> for &'a String {
446
    type Error = ();
447
0
    fn try_from(i: &'a MessageItem) -> Result<&'a String,()> { if let MessageItem::Str(b) = i.peel() { Ok(b) } else { Err(()) } }
448
}
449
450
impl<'a> TryFrom<&'a MessageItem> for &'a Path<'static> {
451
    type Error = ();
452
0
    fn try_from(i: &'a MessageItem) -> Result<&'a Path<'static>,()> { if let MessageItem::ObjectPath(b) = i.peel() { Ok(b) } else { Err(()) } }
453
}
454
455
impl<'a> TryFrom<&'a MessageItem> for &'a Signature<'static> {
456
    type Error = ();
457
0
    fn try_from(i: &'a MessageItem) -> Result<&'a Signature<'static>,()> { if let MessageItem::Signature(b) = i.peel() { Ok(b) } else { Err(()) } }
458
}
459
460
impl<'a> TryFrom<&'a MessageItem> for &'a Box<MessageItem> {
461
    type Error = ();
462
0
    fn try_from(i: &'a MessageItem) -> Result<&'a Box<MessageItem>,()> { if let MessageItem::Variant(b) = i { Ok(b) } else { Err(()) } }
463
}
464
465
impl<'a> TryFrom<&'a MessageItem> for &'a Vec<MessageItem> {
466
    type Error = ();
467
0
    fn try_from(i: &'a MessageItem) -> Result<&'a Vec<MessageItem>,()> {
468
0
        match i.peel() {
469
0
            MessageItem::Array(b) => Ok(&b.v),
470
0
            MessageItem::Struct(b) => Ok(b),
471
0
            _ => Err(()),
472
        }
473
0
    }
474
}
475
476
impl<'a> TryFrom<&'a MessageItem> for &'a [MessageItem] {
477
    type Error = ();
478
0
    fn try_from(i: &'a MessageItem) -> Result<&'a [MessageItem],()> { i.inner::<&Vec<MessageItem>>().map(|s| &**s) }
479
}
480
481
#[cfg(not(feature = "stdfd"))]
482
impl<'a> TryFrom<&'a MessageItem> for &'a OwnedFd {
483
    type Error = ();
484
0
    fn try_from(i: &'a MessageItem) -> Result<&'a OwnedFd,()> { if let MessageItem::UnixFd(ref b) = i { Ok(b) } else { Err(()) } }
485
}
486
487
impl<'a> TryFrom<&'a MessageItem> for &'a [(MessageItem, MessageItem)] {
488
    type Error = ();
489
0
    fn try_from(i: &'a MessageItem) -> Result<&'a [(MessageItem, MessageItem)],()> {
490
0
        if let MessageItem::Dict(ref d) = i { Ok(&*d.v) } else { Err(()) }
491
0
    }
492
}
493
494
495
impl arg::Append for MessageItem {
496
0
    fn append_by_ref(&self, i: &mut IterAppend) {
497
0
        match self {
498
0
            MessageItem::Str(a) => a.append_by_ref(i),
499
0
            MessageItem::Bool(a) => a.append_by_ref(i),
500
0
            MessageItem::Byte(a) => a.append_by_ref(i),
501
0
            MessageItem::Int16(a) => a.append_by_ref(i),
502
0
            MessageItem::Int32(a) => a.append_by_ref(i),
503
0
            MessageItem::Int64(a) => a.append_by_ref(i),
504
0
            MessageItem::UInt16(a) => a.append_by_ref(i),
505
0
            MessageItem::UInt32(a) => a.append_by_ref(i),
506
0
            MessageItem::UInt64(a) => a.append_by_ref(i),
507
0
            MessageItem::Double(a) => a.append_by_ref(i),
508
0
            MessageItem::Array(a) => a.append_by_ref(i),
509
0
            MessageItem::Struct(a) => i.append_container(ArgType::Struct, None, |s| {
510
0
                for v in a { v.append_by_ref(s); }
511
0
            }),
512
0
            MessageItem::Variant(a) => {
513
0
                i.append_container(ArgType::Variant, Some(a.signature().as_cstr()), |s| a.append_by_ref(s))
514
            },
515
0
            MessageItem::Dict(a) => a.append_by_ref(i),
516
0
            MessageItem::ObjectPath(a) => a.append_by_ref(i),
517
0
            MessageItem::Signature(a) => a.append_by_ref(i),
518
            #[cfg(not(feature = "stdfd"))]
519
0
            MessageItem::UnixFd(a) => a.append_by_ref(i),
520
            #[cfg(feature = "stdfd")]
521
            MessageItem::UnixFd(a) => a.0.append_by_ref(i),
522
        }
523
0
    }
524
}
525
526
impl<'a> arg::Get<'a> for MessageItem {
527
0
    fn get(i: &mut Iter<'a>) -> Option<Self> {
528
0
        Some(match i.arg_type() {
529
            ArgType::Array => {
530
0
                let mut s = i.recurse(ArgType::Array).unwrap();
531
0
                if i.signature().as_bytes()[1] == b'{' { // Dict
532
0
                    let mut v = vec!();
533
0
                    while s.arg_type() == ArgType::DictEntry {
534
0
                        let mut ss = s.recurse(ArgType::DictEntry).unwrap();
535
0
                        let kk = MessageItem::get(&mut ss).unwrap();
536
0
                        ss.next();
537
0
                        let vv = MessageItem::get(&mut ss).unwrap();
538
0
                        v.push((kk, vv));
539
0
                        s.next();
540
0
                    };
541
0
                    MessageItem::Dict(MessageItemDict { v: v, sig:  i.signature() })
542
                } else {
543
0
                    let mut v = vec!();
544
0
                    while let Some(mi) = MessageItem::get(&mut s) { v.push(mi); s.next(); };
545
0
                    MessageItem::Array(MessageItemArray { v: v, sig: i.signature() })
546
                }
547
            },
548
0
            ArgType::Variant => MessageItem::Variant({
549
0
                let mut s = i.recurse(ArgType::Variant).unwrap();
550
0
                Box::new(MessageItem::get(&mut s).unwrap())
551
0
            }),
552
0
            ArgType::Boolean => MessageItem::Bool(i.get::<bool>().unwrap()),
553
0
            ArgType::Invalid => return None,
554
0
            ArgType::String => MessageItem::Str(i.get::<String>().unwrap()),
555
0
            ArgType::DictEntry => return None,
556
0
            ArgType::Byte => MessageItem::Byte(i.get::<u8>().unwrap()),
557
0
            ArgType::Int16 => MessageItem::Int16(i.get::<i16>().unwrap()),
558
0
            ArgType::UInt16 => MessageItem::UInt16(i.get::<u16>().unwrap()),
559
0
            ArgType::Int32 => MessageItem::Int32(i.get::<i32>().unwrap()),
560
0
            ArgType::UInt32 => MessageItem::UInt32(i.get::<u32>().unwrap()),
561
0
            ArgType::Int64 => MessageItem::Int64(i.get::<i64>().unwrap()),
562
0
            ArgType::UInt64 => MessageItem::UInt64(i.get::<u64>().unwrap()),
563
0
            ArgType::Double => MessageItem::Double(i.get::<f64>().unwrap()),
564
            #[cfg(not(feature = "stdfd"))]
565
0
            ArgType::UnixFd => MessageItem::UnixFd(i.get::<OwnedFd>().unwrap()),
566
            #[cfg(feature = "stdfd")]
567
            ArgType::UnixFd => MessageItem::UnixFd(MessageItemFd(i.get::<OwnedFd>().unwrap())),
568
            ArgType::Struct => MessageItem::Struct({
569
0
                let mut s = i.recurse(ArgType::Struct).unwrap();
570
0
                let mut v = vec!();
571
0
                while let Some(mi) = MessageItem::get(&mut s) { v.push(mi); s.next(); };
572
0
                v
573
            }),
574
0
            ArgType::ObjectPath => MessageItem::ObjectPath(i.get::<Path>().unwrap().into_static()),
575
0
            ArgType::Signature => MessageItem::Signature(i.get::<Signature>().unwrap().into_static()),
576
        })
577
0
    }
578
}
579
580
impl arg::RefArg for MessageItem {
581
0
    fn arg_type(&self) -> ArgType { MessageItem::arg_type(&self) }
582
0
    fn signature(&self) -> Signature<'static> { MessageItem::signature(&self) }
583
0
    fn append(&self, i: &mut IterAppend) { arg::Append::append_by_ref(self, i) }
584
    #[inline]
585
0
    fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
586
    #[inline]
587
0
    fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
588
    #[inline]
589
0
    fn box_clone(&self) -> Box<dyn arg::RefArg + 'static> { Box::new(self.clone()) }
590
}
591
592
593
impl arg::Append for arg::Variant<MessageItem> {
594
0
    fn append_by_ref(&self, i: &mut IterAppend) {
595
0
        let z = &self.0;
596
0
        let asig = z.signature();
597
0
        let sig = asig.as_cstr();
598
0
        i.append_container(ArgType::Variant, Some(&sig), |s| z.append_by_ref(s));
599
0
    }
600
}
601
602
603
/// Client side properties - get and set properties on a remote application.
604
pub struct Props<'a> {
605
    name: BusName<'a>,
606
    path: Path<'a>,
607
    interface: Interface<'a>,
608
    timeout_ms: i32,
609
    conn: &'a Connection,
610
}
611
612
impl<'a> Props<'a> {
613
    /// Create a new Props.
614
0
    pub fn new<N, P, I>(conn: &'a Connection, name: N, path: P, interface: I, timeout_ms: i32) -> Props<'a>
615
0
    where N: Into<BusName<'a>>, P: Into<Path<'a>>, I: Into<Interface<'a>> {
616
0
        Props {
617
0
            name: name.into(),
618
0
            path: path.into(),
619
0
            interface: interface.into(),
620
0
            timeout_ms: timeout_ms,
621
0
            conn: conn,
622
0
        }
623
0
    }
624
625
    /// Get a single property's value.
626
0
    pub fn get(&self, propname: &str) -> Result<MessageItem, Error> {
627
0
        let mut m = Message::method_call(&self.name, &self.path,
628
0
            &"org.freedesktop.DBus.Properties".into(), &"Get".into());
629
0
        m.append_items(&[self.interface.to_string().into(), propname.to_string().into()]);
630
0
        let mut r = self.conn.send_with_reply_and_block(m, self.timeout_ms)?;
631
0
        let reply = r.as_result()?.get_items();
632
0
        if reply.len() == 1 {
633
0
            if let MessageItem::Variant(ref v) = reply[0] {
634
0
                return Ok((**v).clone())
635
0
            }
636
0
       }
637
0
       let f = format!("Invalid reply for property get {}: '{:?}'", propname, reply);
638
0
       Err(Error::new_custom("InvalidReply", &f))
639
0
    }
640
641
    /// Set a single property's value.
642
0
    pub fn set(&self, propname: &str, value: MessageItem) -> Result<(), Error> {
643
0
        let mut m = Message::method_call(&self.name, &self.path,
644
0
            &"org.freedesktop.DBus.Properties".into(), &"Set".into());
645
0
        m.append_items(&[self.interface.to_string().into(), propname.to_string().into(), Box::new(value).into()]);
646
0
        let mut r = self.conn.send_with_reply_and_block(m, self.timeout_ms)?;
647
0
        r.as_result()?;
648
0
        Ok(())
649
0
    }
650
651
    /// Get a map of all the properties' names and their values.
652
0
    pub fn get_all(&self) -> Result<BTreeMap<String, MessageItem>, Error> {
653
0
        let mut m = Message::method_call(&self.name, &self.path,
654
0
            &"org.freedesktop.DBus.Properties".into(), &"GetAll".into());
655
0
        m.append_items(&[self.interface.to_string().into()]);
656
0
        let mut r = self.conn.send_with_reply_and_block(m, self.timeout_ms)?;
657
0
        let reply = r.as_result()?.get_items();
658
0
659
0
        (|| {
660
0
            if reply.len() != 1 { return Err(()) };
661
0
            let mut tree = BTreeMap::new();
662
0
            let a: &[(MessageItem, MessageItem)] = reply[0].inner()?;
663
0
            for (k, v) in a.iter() {
664
0
                let (k, v): (&String, &Box<MessageItem>) = (k.inner()?, v.inner()?);
665
0
                tree.insert(k.clone(), *v.clone());
666
            }
667
0
            Ok(tree)
668
0
        })().map_err(|_| {
669
0
            let f = format!("Invalid reply for property GetAll: '{:?}'", reply);
670
0
            Error::new_custom("InvalidReply", &f)
671
0
        })
672
0
    }
673
}
674
675
/// Wrapper around Props that keeps a map of fetched properties.
676
pub struct PropHandler<'a> {
677
    p: Props<'a>,
678
    map: BTreeMap<String, MessageItem>,
679
}
680
681
impl<'a> PropHandler<'a> {
682
    /// Create a new PropHandler from a Props.
683
0
    pub fn new(p: Props) -> PropHandler {
684
0
        PropHandler { p: p, map: BTreeMap::new() }
685
0
    }
686
687
    /// Get a map of all the properties' names and their values.
688
0
    pub fn get_all(&mut self) -> Result<(), Error> {
689
0
        self.map = self.p.get_all()?;
690
0
        Ok(())
691
0
    }
692
693
    /// Get a mutable reference to the PropHandler's fetched properties.
694
0
    pub fn map_mut(&mut self) -> &mut BTreeMap<String, MessageItem> { &mut self.map }
695
696
    /// Get a reference to the PropHandler's fetched properties.
697
0
    pub fn map(&self) -> &BTreeMap<String, MessageItem> { &self.map }
698
699
    /// Get a single property's value.
700
0
    pub fn get(&mut self, propname: &str) -> Result<&MessageItem, Error> {
701
0
        let v = self.p.get(propname)?;
702
0
        self.map.insert(propname.to_string(), v);
703
0
        Ok(self.map.get(propname).unwrap())
704
0
    }
705
706
    /// Set a single property's value.
707
0
    pub fn set(&mut self, propname: &str, value: MessageItem) -> Result<(), Error> {
708
0
        self.p.set(propname, value.clone())?;
709
0
        self.map.insert(propname.to_string(), value);
710
0
        Ok(())
711
0
    }
712
}
713
714
715
#[cfg(test)]
716
mod test {
717
    extern crate tempfile;
718
719
    use crate::{Message, MessageType, Path, Signature};
720
    use crate::arg::messageitem::MessageItem;
721
    use crate::ffidisp::{Connection, BusType};
722
723
    #[test]
724
    fn unix_fd() {
725
        use std::io::prelude::*;
726
        use std::io::SeekFrom;
727
        use std::fs::OpenOptions;
728
729
        let c = Connection::get_private(BusType::Session).unwrap();
730
        c.register_object_path("/hello").unwrap();
731
        let mut m = Message::new_method_call(&c.unique_name(), "/hello", "com.example.hello", "Hello").unwrap();
732
        let tempdir = tempfile::Builder::new().prefix("dbus-rs-test").tempdir().unwrap();
733
        let mut filename = tempdir.path().to_path_buf();
734
        filename.push("test");
735
        println!("Creating file {:?}", filename);
736
        let mut file = OpenOptions::new().create(true).read(true).write(true).open(&filename).unwrap();
737
        file.write_all(b"z").unwrap();
738
        file.seek(SeekFrom::Start(0)).unwrap();
739
        #[cfg(unix)]
740
        {
741
            m.append_items(&[file.into()]);
742
        }
743
        println!("Sending {:?}", m.get_items());
744
        c.send(m).unwrap();
745
746
        loop { for n in c.incoming(1000) {
747
            if n.msg_type() == MessageType::MethodCall {
748
                #[cfg(unix)]
749
                {
750
                    use std::os::unix::io::AsRawFd;
751
                    let z: crate::arg::OwnedFd = n.read1().unwrap();
752
                    println!("Got {:?}", z);
753
                    let mut q: libc::c_char = 100;
754
                    assert_eq!(1, unsafe { libc::read(z.as_raw_fd(), &mut q as *mut _ as *mut libc::c_void, 1) });
755
                    assert_eq!(q, 'z' as libc::c_char);
756
                }
757
                return;
758
            } else {
759
                println!("Got {:?}", n);
760
            }
761
        }}
762
    }
763
764
    #[test]
765
    fn message_types() {
766
        let c = Connection::get_private(BusType::Session).unwrap();
767
        c.register_object_path("/hello").unwrap();
768
        let mut m = Message::new_method_call(&c.unique_name(), "/hello", "com.example.hello", "Hello").unwrap();
769
        m.append_items(&[
770
            2000u16.into(),
771
            MessageItem::new_array(vec!(129u8.into())).unwrap(),
772
            ["Hello", "world"][..].into(),
773
            987654321u64.into(),
774
            (-1i32).into(),
775
            format!("Hello world").into(),
776
            (-3.14f64).into(),
777
            MessageItem::Struct(vec!(256i16.into())),
778
            Path::new("/some/path").unwrap().into(),
779
            MessageItem::new_dict(vec!((123543u32.into(), true.into()).into())).unwrap()
780
        ]);
781
        let sending = format!("{:?}", m.get_items());
782
        println!("Sending {}", sending);
783
        c.send(m).unwrap();
784
785
        loop { for n in c.incoming(1000) {
786
            if n.msg_type() == MessageType::MethodCall {
787
                let receiving = format!("{:?}", n.get_items());
788
                println!("Receiving {}", receiving);
789
                assert_eq!(sending, receiving);
790
                return;
791
            } else {
792
                println!("Got {:?}", n);
793
            }
794
        }}
795
    }
796
797
    #[test]
798
    fn dict_of_dicts() {
799
        use std::collections::BTreeMap;
800
801
        let officeactions: BTreeMap<&'static str, MessageItem> = BTreeMap::new();
802
        let mut officethings = BTreeMap::new();
803
        officethings.insert("pencil", 2u16.into());
804
        officethings.insert("paper", 5u16.into());
805
        let mut homethings = BTreeMap::new();
806
        homethings.insert("apple", 11u16.into());
807
        let mut homeifaces = BTreeMap::new();
808
        homeifaces.insert("getThings", homethings);
809
        let mut officeifaces = BTreeMap::new();
810
        officeifaces.insert("getThings", officethings);
811
        officeifaces.insert("getActions", officeactions);
812
        let mut paths = BTreeMap::new();
813
        paths.insert("/hello/office", officeifaces);
814
        paths.insert("/hello/home", homeifaces);
815
816
        println!("Original treemap: {:?}", paths);
817
        let m = MessageItem::new_dict(paths.iter().map(
818
            |(path, ifaces)| (MessageItem::ObjectPath(Path::new(*path).unwrap()),
819
                MessageItem::new_dict(ifaces.iter().map(
820
                    |(iface, props)| (iface.to_string().into(),
821
                        MessageItem::from_dict::<(),_>(props.iter().map(
822
                            |(name, value)| Ok((name.to_string(), value.clone()))
823
                        )).unwrap()
824
                    ).into()
825
                ).collect()).unwrap()
826
            ).into()
827
        ).collect()).unwrap();
828
        println!("As MessageItem: {:?}", m);
829
        assert_eq!(&*m.signature(), "a{oa{sa{sv}}}");
830
831
        let c = Connection::get_private(BusType::Session).unwrap();
832
        c.register_object_path("/hello").unwrap();
833
        let mut msg = Message::new_method_call(&c.unique_name(), "/hello", "org.freedesktop.DBusObjectManager", "GetManagedObjects").unwrap();
834
        msg.append_items(&[m]);
835
        let sending = format!("{:?}", msg.get_items());
836
        println!("Sending {}", sending);
837
        c.send(msg).unwrap();
838
839
        loop { for n in c.incoming(1000) {
840
            if n.msg_type() == MessageType::MethodCall {
841
                let receiving = format!("{:?}", n.get_items());
842
                println!("Receiving {}", receiving);
843
                assert_eq!(sending, receiving);
844
                return;
845
            } else {
846
                println!("Got {:?}", n);
847
            }
848
        } }
849
    }
850
851
    #[test]
852
    fn issue24() {
853
        let c = Connection::get_private(BusType::Session).unwrap();
854
        let mut m = Message::new_method_call("org.test.rust", "/", "org.test.rust", "Test").unwrap();
855
856
        let a = MessageItem::from("test".to_string());
857
        let b = MessageItem::from("test".to_string());
858
        let foo = MessageItem::Struct(vec!(a, b));
859
        let bar = foo.clone();
860
861
        let args = [MessageItem::new_array(vec!(foo, bar)).unwrap()];
862
        println!("{:?}", args);
863
864
        m.append_items(&args);
865
        c.send(m).unwrap();
866
    }
867
868
    /* Unfortunately org.freedesktop.DBus has no properties we can use for testing, but hostname1 should be around on most distros. */
869
    #[cfg(unix)]
870
    #[test]
871
    fn test_get_hostname1_prop() {
872
        use super::Props;
873
874
        let c = Connection::new_system().unwrap();
875
        let p = Props::new(&c, "org.freedesktop.hostname1", "/org/freedesktop/hostname1",
876
            "org.freedesktop.hostname1", 10000);
877
878
        /* Let's use both the get and getall methods and see if we get the same result */
879
        let v = p.get("StaticHostname").unwrap();
880
        let vall = p.get_all().unwrap();
881
        let v2 = vall.get("StaticHostname").unwrap();
882
883
        assert_eq!(&v, &*v2);
884
        match v {
885
            MessageItem::Str(ref s) => { println!("StaticHostname is {}", s); }
886
            _ => { panic!("Invalid Get: {:?}", v); }
887
        };
888
    }
889
890
    #[test]
891
    fn message_listnames() {
892
        let c = Connection::get_private(BusType::Session).unwrap();
893
        let m = Message::method_call(&"org.freedesktop.DBus".into(), &"/".into(),
894
            &"org.freedesktop.DBus".into(), &"ListNames".into());
895
        let r = c.send_with_reply_and_block(m, 2000).unwrap();
896
        let reply = r.get_items();
897
        println!("{:?}", reply);
898
    }
899
900
    #[test]
901
    fn message_namehasowner() {
902
        let c = Connection::get_private(BusType::Session).unwrap();
903
        let mut m = Message::new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "NameHasOwner").unwrap();
904
        m.append_items(&[MessageItem::Str("org.freedesktop.DBus".to_string())]);
905
        let r = c.send_with_reply_and_block(m, 2000).unwrap();
906
        let reply = r.get_items();
907
        println!("{:?}", reply);
908
        assert_eq!(reply, vec!(MessageItem::Bool(true)));
909
    }
910
911
    #[test]
912
    fn message_inner_str() {
913
        let ob = MessageItem::ObjectPath("/path".into());
914
        assert_eq!("/path", ob.inner::<&str>().unwrap());
915
916
        let ob = MessageItem::ObjectPath("/path".into());
917
        assert_ne!("/path/another", ob.inner::<&str>().unwrap());
918
919
        let ob = MessageItem::Str("String".into());
920
        assert_eq!("String", ob.inner::<&str>().unwrap());
921
922
        let ob = MessageItem::Str("String".into());
923
        assert_ne!("StringDiff", ob.inner::<&str>().unwrap());
924
925
        let ob = MessageItem::Signature(Signature::make::<i32>());
926
        assert_eq!("i", ob.inner::<&str>().unwrap());
927
928
        let ob = MessageItem::Signature(Signature::make::<u32>());
929
        assert_ne!("i", ob.inner::<&str>().unwrap());
930
931
    }
932
933
    #[test]
934
    fn message_peel() {
935
        let flat_str = MessageItem::Str("foobar".into());
936
        assert_eq!(flat_str.peel(), &flat_str);
937
938
        let flat_path = MessageItem::ObjectPath("/path".into());
939
        assert_eq!(flat_path.peel(), &flat_path);
940
941
        let flat_sig = MessageItem::Signature(Signature::make::<i32>());
942
        assert_eq!(flat_sig.peel(), &flat_sig);
943
944
        let flat_int = MessageItem::Int32(1234);
945
        assert_eq!(flat_int.peel(), &flat_int);
946
947
        let layered_str = MessageItem::Variant(Box::new(flat_str));
948
        assert_eq!(layered_str.peel(), &MessageItem::Str("foobar".into()));
949
950
        let layered_path = MessageItem::Variant(Box::new(flat_path));
951
        assert_eq!(layered_path.peel(), &MessageItem::ObjectPath("/path".into()));
952
953
        let layered_sig = MessageItem::Variant(Box::new(flat_sig));
954
        assert_eq!(layered_sig.peel(), &MessageItem::Signature(Signature::make::<i32>()));
955
956
        let layered_int = MessageItem::Variant(Box::new(flat_int));
957
        assert_eq!(layered_int.peel(), &MessageItem::Int32(1234));
958
959
        let very_deep =
960
            MessageItem::Variant(Box::new(
961
            MessageItem::Variant(Box::new(
962
            MessageItem::Variant(Box::new(
963
            MessageItem::Variant(Box::new(
964
            MessageItem::Variant(Box::new(
965
            MessageItem::Variant(Box::new(
966
            MessageItem::Variant(Box::new(
967
            MessageItem::Variant(Box::new(
968
            MessageItem::Variant(Box::new(
969
            MessageItem::Variant(Box::new(
970
            MessageItem::Int32(1234)
971
            ))))))))))))))))))));
972
973
        assert_eq!(very_deep.peel(), &MessageItem::Int32(1234));
974
975
    }
976
977
    #[test]
978
    fn inner_from_variant() {
979
        let msg_u8 = MessageItem::Variant(Box::new(3u8.into()));
980
        assert_eq!(msg_u8.inner::<u8>().unwrap(), 3u8);
981
982
        let msg_u16 = MessageItem::Variant(Box::new(4u16.into()));
983
        assert_eq!(msg_u16.inner::<u16>().unwrap(), 4u16);
984
985
        let msg_u32 = MessageItem::Variant(Box::new(5u32.into()));
986
        assert_eq!(msg_u32.inner::<u32>().unwrap(), 5u32);
987
988
        let msg_u64 = MessageItem::Variant(Box::new(6u64.into()));
989
        assert_eq!(msg_u64.inner::<u64>().unwrap(), 6u64);
990
991
        let msg_i16 = MessageItem::Variant(Box::new(4i16.into()));
992
        assert_eq!(msg_i16.inner::<i16>().unwrap(), 4i16);
993
994
        let msg_i32 = MessageItem::Variant(Box::new(5i32.into()));
995
        assert_eq!(msg_i32.inner::<i32>().unwrap(), 5i32);
996
997
        let msg_i64 = MessageItem::Variant(Box::new(6i64.into()));
998
        assert_eq!(msg_i64.inner::<i64>().unwrap(), 6i64);
999
1000
        let msg_f64 = MessageItem::Variant(Box::new(6.5f64.into()));
1001
        assert_eq!(msg_f64.inner::<f64>().unwrap(), 6.5f64);
1002
1003
        let msg_bool = MessageItem::Variant(Box::new(false.into()));
1004
        assert_eq!(msg_bool.inner::<bool>().unwrap(), false);
1005
1006
        let msg_string = MessageItem::Variant(Box::new("asdf".to_string().into()));
1007
        assert_eq!(msg_string.inner::<&String>().unwrap(), "asdf");
1008
1009
        let path: Path = "/path".into();
1010
        let msg_path = MessageItem::Variant(Box::new(MessageItem::ObjectPath(path.clone())));
1011
        assert_eq!(msg_path.inner::<&Path>().unwrap(), &path);
1012
1013
        let sig: Signature = "a{si}".into();
1014
        let msg_sig = MessageItem::Variant(Box::new(MessageItem::Signature(sig.clone())));
1015
        assert_eq!(msg_sig.inner::<&Signature>().unwrap(), &sig);
1016
1017
        assert_eq!(msg_string.inner::<&str>().unwrap(), "asdf");
1018
        assert_eq!(msg_path.inner::<&str>().unwrap(), "/path");
1019
        assert_eq!(msg_sig.inner::<&str>().unwrap(), "a{si}");
1020
1021
    }
1022
1023
}