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