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(signature:"(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: &ObjectPath<'_>) => (MessageFieldCode::Path, value.clone().into()),
134 MessageField::Interface(value: &InterfaceName<'_>) => (MessageFieldCode::Interface, value.as_str().into()),
135 MessageField::Member(value: &MemberName<'_>) => (MessageFieldCode::Member, value.as_str().into()),
136 MessageField::ErrorName(value: &ErrorName<'_>) => (MessageFieldCode::ErrorName, value.as_str().into()),
137 MessageField::ReplySerial(value: &u32) => (MessageFieldCode::ReplySerial, (*value).into()),
138 MessageField::Destination(value: &BusName<'_>) => {
139 (MessageFieldCode::Destination, value.as_str().into())
140 }
141 MessageField::Sender(value: &UniqueName<'_>) => (MessageFieldCode::Sender, value.as_str().into()),
142 MessageField::Signature(value: &Signature<'_>) => (MessageFieldCode::Signature, value.clone().into()),
143 MessageField::UnixFDs(value: &u32) => (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}
201