zbus/
message_field.rs

1use std::convert::TryFrom;
2
3use serde::{
4    de::{Deserialize, Deserializer, Error},
5    ser::{Serialize, Serializer},
6};
7use serde_repr::{Deserialize_repr, Serialize_repr};
8
9use static_assertions::assert_impl_all;
10use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName};
11use zvariant::{ObjectPath, Signature, Type, Value};
12
13/// The message field code.
14///
15/// Every [`MessageField`] has an associated code. This is mostly an internal D-Bus protocol detail
16/// that you would not need to ever care about when using the high-level API. When using the
17/// low-level API, this is how you can [retrieve a specific field] from [`MessageFields`].
18///
19/// [`MessageField`]: enum.MessageField.html
20/// [retrieve a specific field]: struct.MessageFields.html#method.get_field
21/// [`MessageFields`]: struct.MessageFields.html
22#[repr(u8)]
23#[derive(Copy, Clone, Debug, Deserialize_repr, PartialEq, Eq, Serialize_repr, Type)]
24pub enum MessageFieldCode {
25    /// Code for [`MessageField::Invalid`](enum.MessageField.html#variant.Invalid)
26    Invalid = 0,
27    /// Code for [`MessageField::Path`](enum.MessageField.html#variant.Path)
28    Path = 1,
29    /// Code for [`MessageField::Interface`](enum.MessageField.html#variant.Interface)
30    Interface = 2,
31    /// Code for [`MessageField::Member`](enum.MessageField.html#variant.Member)
32    Member = 3,
33    /// Code for [`MessageField::ErrorName`](enum.MessageField.html#variant.ErrorName)
34    ErrorName = 4,
35    /// Code for [`MessageField::ReplySerial`](enum.MessageField.html#variant.ReplySerial)
36    ReplySerial = 5,
37    /// Code for [`MessageField::Destinatione`](enum.MessageField.html#variant.Destination)
38    Destination = 6,
39    /// Code for [`MessageField::Sender`](enum.MessageField.html#variant.Sender)
40    Sender = 7,
41    /// Code for [`MessageField::Signature`](enum.MessageField.html#variant.Signature)
42    Signature = 8,
43    /// Code for [`MessageField::UnixFDs`](enum.MessageField.html#variant.UnixFDs)
44    UnixFDs = 9,
45}
46
47assert_impl_all!(MessageFieldCode: Send, Sync, Unpin);
48
49impl From<u8> for MessageFieldCode {
50    fn from(val: u8) -> MessageFieldCode {
51        match val {
52            1 => MessageFieldCode::Path,
53            2 => MessageFieldCode::Interface,
54            3 => MessageFieldCode::Member,
55            4 => MessageFieldCode::ErrorName,
56            5 => MessageFieldCode::ReplySerial,
57            6 => MessageFieldCode::Destination,
58            7 => MessageFieldCode::Sender,
59            8 => MessageFieldCode::Signature,
60            9 => MessageFieldCode::UnixFDs,
61            _ => MessageFieldCode::Invalid,
62        }
63    }
64}
65
66impl<'f> MessageField<'f> {
67    /// Get the associated code for this field.
68    pub fn code(&self) -> MessageFieldCode {
69        match self {
70            MessageField::Path(_) => MessageFieldCode::Path,
71            MessageField::Interface(_) => MessageFieldCode::Interface,
72            MessageField::Member(_) => MessageFieldCode::Member,
73            MessageField::ErrorName(_) => MessageFieldCode::ErrorName,
74            MessageField::ReplySerial(_) => MessageFieldCode::ReplySerial,
75            MessageField::Destination(_) => MessageFieldCode::Destination,
76            MessageField::Sender(_) => MessageFieldCode::Sender,
77            MessageField::Signature(_) => MessageFieldCode::Signature,
78            MessageField::UnixFDs(_) => MessageFieldCode::UnixFDs,
79            MessageField::Invalid => MessageFieldCode::Invalid,
80        }
81    }
82}
83
84/// The dynamic message header.
85///
86/// All D-Bus messages contain a set of metadata [headers]. Some of these headers [are fixed] for
87/// all types of messages, while others depend on the type of the message in question. The latter
88/// are called message fields.
89///
90/// Please consult the [Message Format] section of the D-Bus spec for more details.
91///
92/// [headers]: struct.MessageHeader.html
93/// [are fixed]: struct.MessagePrimaryHeader.html
94/// [Message Format]: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
95#[derive(Clone, Debug, PartialEq, Eq)]
96pub enum MessageField<'f> {
97    /// Not a valid field.
98    Invalid,
99    /// The object to send a call to, or the object a signal is emitted from.
100    Path(ObjectPath<'f>),
101    /// The interface to invoke a method call on, or that a signal is emitted from.
102    Interface(InterfaceName<'f>),
103    /// The member, either the method name or signal name.
104    Member(MemberName<'f>),
105    /// The name of the error that occurred, for errors
106    ErrorName(ErrorName<'f>),
107    /// The serial number of the message this message is a reply to.
108    ReplySerial(u32),
109    /// The name of the connection this message is intended for.
110    Destination(BusName<'f>),
111    /// Unique name of the sending connection.
112    Sender(UniqueName<'f>),
113    /// The signature of the message body.
114    Signature(Signature<'f>),
115    /// The number of Unix file descriptors that accompany the message.
116    UnixFDs(u32),
117}
118
119assert_impl_all!(MessageField<'_>: Send, Sync, Unpin);
120
121impl<'f> Type for MessageField<'f> {
122    fn signature() -> Signature<'static> {
123        Signature::from_static_str_unchecked("(yv)")
124    }
125}
126
127impl<'f> Serialize for MessageField<'f> {
128    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
129    where
130        S: Serializer,
131    {
132        let tuple: (MessageFieldCode, Value<'_>) = match self {
133            MessageField::Path(value) => (MessageFieldCode::Path, value.clone().into()),
134            MessageField::Interface(value) => (MessageFieldCode::Interface, value.as_str().into()),
135            MessageField::Member(value) => (MessageFieldCode::Member, value.as_str().into()),
136            MessageField::ErrorName(value) => (MessageFieldCode::ErrorName, value.as_str().into()),
137            MessageField::ReplySerial(value) => (MessageFieldCode::ReplySerial, (*value).into()),
138            MessageField::Destination(value) => {
139                (MessageFieldCode::Destination, value.as_str().into())
140            }
141            MessageField::Sender(value) => (MessageFieldCode::Sender, value.as_str().into()),
142            MessageField::Signature(value) => (MessageFieldCode::Signature, value.clone().into()),
143            MessageField::UnixFDs(value) => (MessageFieldCode::UnixFDs, (*value).into()),
144            // This is a programmer error
145            MessageField::Invalid => panic!("Attempt to serialize invalid MessageField"),
146        };
147
148        tuple.serialize(serializer)
149    }
150}
151
152impl<'de: 'f, 'f> Deserialize<'de> for MessageField<'f> {
153    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
154    where
155        D: Deserializer<'de>,
156    {
157        let (code, value) = <(MessageFieldCode, Value<'_>)>::deserialize(deserializer)?;
158        Ok(match code {
159            MessageFieldCode::Path => {
160                MessageField::Path(ObjectPath::try_from(value).map_err(D::Error::custom)?)
161            }
162            MessageFieldCode::Interface => {
163                MessageField::Interface(InterfaceName::try_from(value).map_err(D::Error::custom)?)
164            }
165            MessageFieldCode::Member => {
166                MessageField::Member(MemberName::try_from(value).map_err(D::Error::custom)?)
167            }
168            MessageFieldCode::ErrorName => MessageField::ErrorName(
169                ErrorName::try_from(value)
170                    .map(Into::into)
171                    .map_err(D::Error::custom)?,
172            ),
173            MessageFieldCode::ReplySerial => {
174                MessageField::ReplySerial(u32::try_from(value).map_err(D::Error::custom)?)
175            }
176            MessageFieldCode::Destination => MessageField::Destination(
177                BusName::try_from(value)
178                    .map(Into::into)
179                    .map_err(D::Error::custom)?,
180            ),
181            MessageFieldCode::Sender => MessageField::Sender(
182                UniqueName::try_from(value)
183                    .map(Into::into)
184                    .map_err(D::Error::custom)?,
185            ),
186            MessageFieldCode::Signature => {
187                MessageField::Signature(Signature::try_from(value).map_err(D::Error::custom)?)
188            }
189            MessageFieldCode::UnixFDs => {
190                MessageField::UnixFDs(u32::try_from(value).map_err(D::Error::custom)?)
191            }
192            MessageFieldCode::Invalid => {
193                return Err(Error::invalid_value(
194                    serde::de::Unexpected::Unsigned(code as u64),
195                    &"A valid D-Bus message field code",
196                ));
197            }
198        })
199    }
200}