1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::{Bus, DecodeError, Error, Interface, Member, ObjectPath, Value};
use std::convert::TryFrom;

/// An enum representing a [header field].
///
/// [header field]: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields
#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
pub enum MessageHeaderField {
    Path(ObjectPath),
    Interface(Interface),
    Member(Member),
    ErrorName(Error),
    ReplySerial(u32),
    Destination(Bus),
    Sender(Bus),
    Signature(String),
    #[cfg(target_family = "unix")]
    UnixFDs(u32),
}

impl TryFrom<Value> for MessageHeaderField {
    type Error = DecodeError;

    fn try_from(v: Value) -> Result<Self, Self::Error> {
        // The outer `Value` has to be a struct.
        if let Value::Struct(mut values) = v {
            // The length of the struct have to be 2
            if values.len() == 2 {
                // Check if the second is a Variant and unwrap the value.
                let v: Value = if let Value::Variant(v) = values.pop().unwrap() {
                    *v
                } else {
                    return Err(DecodeError::Header);
                };
                // Check if the first is a byte
                if let Value::Byte(b) = values.pop().unwrap() {
                    match b {
                        1 => {
                            // The header field is a Path.
                            if let Value::ObjectPath(o) = v {
                                Ok(MessageHeaderField::Path(o))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        2 => {
                            // The header field is an Interface.
                            if let Value::String(s) = v {
                                Ok(MessageHeaderField::Interface(Interface::try_from(s)?))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        3 => {
                            // The header field is an Member.
                            if let Value::String(s) = v {
                                Ok(MessageHeaderField::Member(Member::try_from(s)?))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        4 => {
                            // The header field is an ErrorName.
                            if let Value::String(s) = v {
                                Ok(MessageHeaderField::ErrorName(Error::try_from(s)?))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        5 => {
                            // The header field is a ReplySerial.
                            if let Value::Uint32(u) = v {
                                Ok(MessageHeaderField::ReplySerial(u))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        6 => {
                            // The header field is a Destination.
                            if let Value::String(s) = v {
                                Ok(MessageHeaderField::Destination(Bus::try_from(s)?))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        7 => {
                            // The header field is a Sender.
                            if let Value::String(s) = v {
                                Ok(MessageHeaderField::Sender(Bus::try_from(s)?))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        8 => {
                            // The header field is a Signature.
                            if let Value::Signature(s) = v {
                                Ok(MessageHeaderField::Signature(s))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        #[cfg(target_family = "unix")]
                        9 => {
                            // The header field is a UnixFds.
                            if let Value::Uint32(u) = v {
                                Ok(MessageHeaderField::UnixFDs(u))
                            } else {
                                Err(DecodeError::Header)
                            }
                        }
                        _ => {
                            // Invalid number.
                            Err(DecodeError::Header)
                        }
                    }
                } else {
                    Err(DecodeError::Header)
                }
            } else {
                Err(DecodeError::Header)
            }
        } else {
            Err(DecodeError::Header)
        }
    }
}