use std::convert::TryFrom;
use serde::{
de::{Deserialize, Deserializer, Error},
ser::{Serialize, Serializer},
};
use serde_repr::{Deserialize_repr, Serialize_repr};
use static_assertions::assert_impl_all;
use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName};
use zvariant::{ObjectPath, Signature, Type, Value};
#[repr(u8)]
#[derive(Copy, Clone, Debug, Deserialize_repr, PartialEq, Eq, Serialize_repr, Type)]
pub enum MessageFieldCode {
Invalid = 0,
Path = 1,
Interface = 2,
Member = 3,
ErrorName = 4,
ReplySerial = 5,
Destination = 6,
Sender = 7,
Signature = 8,
UnixFDs = 9,
}
assert_impl_all!(MessageFieldCode: Send, Sync, Unpin);
impl From<u8> for MessageFieldCode {
fn from(val: u8) -> MessageFieldCode {
match val {
1 => MessageFieldCode::Path,
2 => MessageFieldCode::Interface,
3 => MessageFieldCode::Member,
4 => MessageFieldCode::ErrorName,
5 => MessageFieldCode::ReplySerial,
6 => MessageFieldCode::Destination,
7 => MessageFieldCode::Sender,
8 => MessageFieldCode::Signature,
9 => MessageFieldCode::UnixFDs,
_ => MessageFieldCode::Invalid,
}
}
}
impl<'f> MessageField<'f> {
pub fn code(&self) -> MessageFieldCode {
match self {
MessageField::Path(_) => MessageFieldCode::Path,
MessageField::Interface(_) => MessageFieldCode::Interface,
MessageField::Member(_) => MessageFieldCode::Member,
MessageField::ErrorName(_) => MessageFieldCode::ErrorName,
MessageField::ReplySerial(_) => MessageFieldCode::ReplySerial,
MessageField::Destination(_) => MessageFieldCode::Destination,
MessageField::Sender(_) => MessageFieldCode::Sender,
MessageField::Signature(_) => MessageFieldCode::Signature,
MessageField::UnixFDs(_) => MessageFieldCode::UnixFDs,
MessageField::Invalid => MessageFieldCode::Invalid,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MessageField<'f> {
Invalid,
Path(ObjectPath<'f>),
Interface(InterfaceName<'f>),
Member(MemberName<'f>),
ErrorName(ErrorName<'f>),
ReplySerial(u32),
Destination(BusName<'f>),
Sender(UniqueName<'f>),
Signature(Signature<'f>),
UnixFDs(u32),
}
assert_impl_all!(MessageField<'_>: Send, Sync, Unpin);
impl<'f> Type for MessageField<'f> {
fn signature() -> Signature<'static> {
Signature::from_static_str_unchecked("(yv)")
}
}
impl<'f> Serialize for MessageField<'f> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let tuple: (MessageFieldCode, Value<'_>) = match self {
MessageField::Path(value) => (MessageFieldCode::Path, value.clone().into()),
MessageField::Interface(value) => (MessageFieldCode::Interface, value.as_str().into()),
MessageField::Member(value) => (MessageFieldCode::Member, value.as_str().into()),
MessageField::ErrorName(value) => (MessageFieldCode::ErrorName, value.as_str().into()),
MessageField::ReplySerial(value) => (MessageFieldCode::ReplySerial, (*value).into()),
MessageField::Destination(value) => {
(MessageFieldCode::Destination, value.as_str().into())
}
MessageField::Sender(value) => (MessageFieldCode::Sender, value.as_str().into()),
MessageField::Signature(value) => (MessageFieldCode::Signature, value.clone().into()),
MessageField::UnixFDs(value) => (MessageFieldCode::UnixFDs, (*value).into()),
MessageField::Invalid => panic!("Attempt to serialize invalid MessageField"),
};
tuple.serialize(serializer)
}
}
impl<'de: 'f, 'f> Deserialize<'de> for MessageField<'f> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let (code, value) = <(MessageFieldCode, Value<'_>)>::deserialize(deserializer)?;
Ok(match code {
MessageFieldCode::Path => {
MessageField::Path(ObjectPath::try_from(value).map_err(D::Error::custom)?)
}
MessageFieldCode::Interface => {
MessageField::Interface(InterfaceName::try_from(value).map_err(D::Error::custom)?)
}
MessageFieldCode::Member => {
MessageField::Member(MemberName::try_from(value).map_err(D::Error::custom)?)
}
MessageFieldCode::ErrorName => MessageField::ErrorName(
ErrorName::try_from(value)
.map(Into::into)
.map_err(D::Error::custom)?,
),
MessageFieldCode::ReplySerial => {
MessageField::ReplySerial(u32::try_from(value).map_err(D::Error::custom)?)
}
MessageFieldCode::Destination => MessageField::Destination(
BusName::try_from(value)
.map(Into::into)
.map_err(D::Error::custom)?,
),
MessageFieldCode::Sender => MessageField::Sender(
UniqueName::try_from(value)
.map(Into::into)
.map_err(D::Error::custom)?,
),
MessageFieldCode::Signature => {
MessageField::Signature(Signature::try_from(value).map_err(D::Error::custom)?)
}
MessageFieldCode::UnixFDs => {
MessageField::UnixFDs(u32::try_from(value).map_err(D::Error::custom)?)
}
MessageFieldCode::Invalid => {
return Err(Error::invalid_value(
serde::de::Unexpected::Unsigned(code as u64),
&"A valid D-Bus message field code",
));
}
})
}
}