dbus_message_parser/message/header/
fields.rs

1use crate::value::{
2    Bus, BusError, Error, ErrorError, Interface, InterfaceError, Member, MemberError, ObjectPath,
3    Struct, Type, Value,
4};
5use std::convert::TryFrom;
6use thiserror::Error as ThisError;
7
8macro_rules! try_set_field {
9    ($function:ident, $field:ident, $variant:ident, $multiple_error:ident, $error:ident $(,$convert:expr)?) => {
10        fn $function(&mut self, v: Value) -> Result<(), FieldsError> {
11            if self.$field.is_some() {
12                return Err(FieldsError::$multiple_error(v));
13            }
14
15            match v {
16                Value::$variant(o) => {
17                    $(let o = $convert(o)?;)?
18                    self.$field = Some(o);
19                    Ok(())
20                }
21                v => Err(FieldsError::$error(v)),
22            }
23        }
24    };
25}
26
27macro_rules! add_to_vec {
28    ($vec:ident, $fields:ident, $field:ident, $number:literal, $variant:ident $(,$convert:ident)?) => {
29        if let Some(v) = $fields.$field {
30            $(let v = v.$convert();)?
31            $vec.push(Value::Struct(Struct(vec![
32                Value::Byte($number),
33                Value::Variant(Box::new(Value::$variant(v))),
34            ])));
35        }
36    };
37}
38
39#[derive(Debug, PartialEq, ThisError)]
40pub enum FieldsError {
41    #[error("Value is not a Struct: {0:?}")]
42    Struct(Value),
43    #[error("Struct does not contain exactly two values: {0}")]
44    Length(usize),
45    #[error("Second value is not a Variant: {0:?}")]
46    Variant(Value),
47    #[error("First value is not a Byte: {0:?}")]
48    Byte(Value),
49    #[error("Variant does not contain a ObjectPath: {0:?}")]
50    Path(Value),
51    #[error("Variant does not contain a String: {0:?}")]
52    Interface(Value),
53    #[error("String could not be converted to an Interface: {0}")]
54    InterfaceError(#[from] InterfaceError),
55    #[error("Variant does not contain a String: {0:?}")]
56    Member(Value),
57    #[error("String could not be converted to an Member: {0}")]
58    MemberError(#[from] MemberError),
59    #[error("Variant does not contain a String: {0:?}")]
60    ErrorName(Value),
61    #[error("String could not be converted to an ErrorName: {0}")]
62    ErrorError(#[from] ErrorError),
63    #[error("Variant does not contain a Uint32: {0:?}")]
64    ReplySerial(Value),
65    #[error("")]
66    BusError(#[from] BusError),
67    #[error("Variant does not contain a String: {0:?}")]
68    Destination(Value),
69    #[error("Variant does not contain a String: {0:?}")]
70    Sender(Value),
71    #[error("Variant does not contain a Signature: {0:?}")]
72    Signature(Value),
73    #[cfg(target_family = "unix")]
74    #[error("Variant does not contain a Uint32: {0:?}")]
75    UnixFDs(Value),
76    #[error("The byte does not has a valid number: {0}")]
77    InvalidNumber(u8),
78    #[error("The path is defined mutlple times: {0:?}")]
79    MultiplePath(Value),
80    #[error("The interface is defined mutlple times: {0:?}")]
81    MultipleInterface(Value),
82    #[error("The member is defined mutlple times: {0:?}")]
83    MultipleMember(Value),
84    #[error("The error name is defined mutlple times: {0:?}")]
85    MultipleErrorName(Value),
86    #[error("The reply serial is defined mutlple times: {0:?}")]
87    MultipleReplySerial(Value),
88    #[error("The destination is defined mutlple times: {0:?}")]
89    MultipleDestination(Value),
90    #[error("The destination is defined mutlple times: {0:?}")]
91    MultipleSender(Value),
92    #[error("The signature is defined mutlple times: {0:?}")]
93    MultipleSignature(Value),
94    #[cfg(target_family = "unix")]
95    #[error("The unix fds is defined mutlple times: {0:?}")]
96    MultipleUnixFDs(Value),
97}
98
99/// An struct representing the [header fields].
100///
101/// [header fields]: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields
102#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq, Default)]
103pub struct Fields {
104    pub path: Option<ObjectPath>,
105    pub interface: Option<Interface>,
106    pub member: Option<Member>,
107    pub error_name: Option<Error>,
108    pub reply_serial: Option<u32>,
109    pub destination: Option<Bus>,
110    pub sender: Option<Bus>,
111    pub signature: Option<Vec<Type>>,
112    #[cfg(target_family = "unix")]
113    pub unix_fds: Option<u32>,
114}
115
116impl Fields {
117    try_set_field!(try_set_path, path, ObjectPath, MultiplePath, Path);
118    try_set_field!(
119        try_set_interface,
120        interface,
121        String,
122        MultipleInterface,
123        Interface,
124        Interface::try_from
125    );
126    try_set_field!(
127        try_set_member,
128        member,
129        String,
130        MultipleMember,
131        Member,
132        Member::try_from
133    );
134    try_set_field!(
135        try_set_error_name,
136        error_name,
137        String,
138        MultipleErrorName,
139        ErrorName,
140        Error::try_from
141    );
142    try_set_field!(
143        try_set_reply_serial,
144        reply_serial,
145        Uint32,
146        MultipleReplySerial,
147        ReplySerial
148    );
149    try_set_field!(
150        try_set_destination,
151        destination,
152        String,
153        MultipleDestination,
154        Destination,
155        Bus::try_from
156    );
157    try_set_field!(
158        try_set_sender,
159        sender,
160        String,
161        MultipleSender,
162        Sender,
163        Bus::try_from
164    );
165    try_set_field!(
166        try_set_signature,
167        signature,
168        Signature,
169        MultipleSignature,
170        Signature
171    );
172    #[cfg(target_family = "unix")]
173    try_set_field!(try_set_unix_fds, unix_fds, Uint32, MultipleUnixFDs, UnixFDs);
174
175    fn try_set_field(&mut self, b: u8, v: Value) -> Result<(), FieldsError> {
176        match b {
177            1 => self.try_set_path(v),
178            2 => self.try_set_interface(v),
179            3 => self.try_set_member(v),
180            4 => self.try_set_error_name(v),
181            5 => self.try_set_reply_serial(v),
182            6 => self.try_set_destination(v),
183            7 => self.try_set_sender(v),
184            8 => self.try_set_signature(v),
185            #[cfg(target_family = "unix")]
186            9 => self.try_set_unix_fds(v),
187            // Invalid number.
188            b => Err(FieldsError::InvalidNumber(b)),
189        }
190    }
191}
192
193fn unwrap_value(value: Value) -> Result<(u8, Value), FieldsError> {
194    // The outer `Value` has to be a struct.
195    let mut values: Vec<Value> = match value {
196        Value::Struct(struct_) => struct_.into(),
197        v => return Err(FieldsError::Struct(v)),
198    };
199    // The length of the struct have to be 2
200    let values_len = values.len();
201    if values_len != 2 {
202        return Err(FieldsError::Length(values_len));
203    }
204    // Check if the second is a Variant and unwrap the value.
205    let v = match values.pop().unwrap() {
206        Value::Variant(v) => *v,
207        v => return Err(FieldsError::Variant(v)),
208    };
209    // Check if the first is a byte
210    let b = match values.pop().unwrap() {
211        Value::Byte(b) => b,
212        v => return Err(FieldsError::Byte(v)),
213    };
214
215    Ok((b, v))
216}
217
218impl TryFrom<Vec<Value>> for Fields {
219    type Error = FieldsError;
220
221    fn try_from(values: Vec<Value>) -> Result<Self, Self::Error> {
222        let mut fields = Fields::default();
223
224        for value in values {
225            let (b, v) = unwrap_value(value)?;
226            fields.try_set_field(b, v)?;
227        }
228
229        Ok(fields)
230    }
231}
232
233impl From<Fields> for Vec<Value> {
234    fn from(fields: Fields) -> Self {
235        let mut values = Vec::new();
236
237        add_to_vec!(values, fields, path, 1, ObjectPath);
238        add_to_vec!(values, fields, interface, 2, String, to_string);
239        add_to_vec!(values, fields, member, 3, String, to_string);
240        add_to_vec!(values, fields, error_name, 4, String, to_string);
241        add_to_vec!(values, fields, reply_serial, 5, Uint32);
242        add_to_vec!(values, fields, destination, 6, String, to_string);
243        add_to_vec!(values, fields, sender, 7, String, to_string);
244        add_to_vec!(values, fields, signature, 8, Signature);
245        #[cfg(target_family = "unix")]
246        add_to_vec!(values, fields, unix_fds, 9, Uint32);
247        values
248    }
249}