1 | use std::convert::TryFrom; |
2 | |
3 | use serde::{ |
4 | de::{Deserialize, Deserializer, Error}, |
5 | ser::{Serialize, Serializer}, |
6 | }; |
7 | use serde_repr::{Deserialize_repr, Serialize_repr}; |
8 | |
9 | use static_assertions::assert_impl_all; |
10 | use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName}; |
11 | use 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)] |
24 | pub 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 | |
47 | assert_impl_all!(MessageFieldCode: Send, Sync, Unpin); |
48 | |
49 | impl 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 | |
66 | impl<'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)] |
96 | pub 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 | |
119 | assert_impl_all!(MessageField<'_>: Send, Sync, Unpin); |
120 | |
121 | impl<'f> Type for MessageField<'f> { |
122 | fn signature() -> Signature<'static> { |
123 | Signature::from_static_str_unchecked(signature:"(yv)" ) |
124 | } |
125 | } |
126 | |
127 | impl<'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 | |
152 | impl<'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 | |