use std::num::NonZeroU32;
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(crate) enum FieldCode {
Path = 1,
Interface = 2,
Member = 3,
ErrorName = 4,
ReplySerial = 5,
Destination = 6,
Sender = 7,
Signature = 8,
UnixFDs = 9,
}
assert_impl_all!(FieldCode: Send, Sync, Unpin);
impl<'f> Field<'f> {
pub fn code(&self) -> FieldCode {
match self {
Field::Path(_) => FieldCode::Path,
Field::Interface(_) => FieldCode::Interface,
Field::Member(_) => FieldCode::Member,
Field::ErrorName(_) => FieldCode::ErrorName,
Field::ReplySerial(_) => FieldCode::ReplySerial,
Field::Destination(_) => FieldCode::Destination,
Field::Sender(_) => FieldCode::Sender,
Field::Signature(_) => FieldCode::Signature,
Field::UnixFDs(_) => FieldCode::UnixFDs,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum Field<'f> {
Path(ObjectPath<'f>),
Interface(InterfaceName<'f>),
Member(MemberName<'f>),
ErrorName(ErrorName<'f>),
ReplySerial(NonZeroU32),
Destination(BusName<'f>),
Sender(UniqueName<'f>),
Signature(Signature<'f>),
UnixFDs(u32),
}
assert_impl_all!(Field<'_>: Send, Sync, Unpin);
impl<'f> Type for Field<'f> {
fn signature() -> Signature<'static> {
Signature::from_static_str_unchecked("(yv)")
}
}
impl<'f> Serialize for Field<'f> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let tuple: (FieldCode, Value<'_>) = match self {
Field::Path(value) => (FieldCode::Path, value.as_ref().into()),
Field::Interface(value) => (FieldCode::Interface, value.as_str().into()),
Field::Member(value) => (FieldCode::Member, value.as_str().into()),
Field::ErrorName(value) => (FieldCode::ErrorName, value.as_str().into()),
Field::ReplySerial(value) => (FieldCode::ReplySerial, value.get().into()),
Field::Destination(value) => (FieldCode::Destination, value.as_str().into()),
Field::Sender(value) => (FieldCode::Sender, value.as_str().into()),
Field::Signature(value) => (FieldCode::Signature, value.as_ref().into()),
Field::UnixFDs(value) => (FieldCode::UnixFDs, (*value).into()),
};
tuple.serialize(serializer)
}
}
impl<'de: 'f, 'f> Deserialize<'de> for Field<'f> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let (code, value) = <(FieldCode, Value<'_>)>::deserialize(deserializer)?;
Ok(match code {
FieldCode::Path => Field::Path(ObjectPath::try_from(value).map_err(D::Error::custom)?),
FieldCode::Interface => {
Field::Interface(InterfaceName::try_from(value).map_err(D::Error::custom)?)
}
FieldCode::Member => {
Field::Member(MemberName::try_from(value).map_err(D::Error::custom)?)
}
FieldCode::ErrorName => Field::ErrorName(
ErrorName::try_from(value)
.map(Into::into)
.map_err(D::Error::custom)?,
),
FieldCode::ReplySerial => {
let value = u32::try_from(value)
.map_err(D::Error::custom)
.and_then(|v| v.try_into().map_err(D::Error::custom))?;
Field::ReplySerial(value)
}
FieldCode::Destination => Field::Destination(
BusName::try_from(value)
.map(Into::into)
.map_err(D::Error::custom)?,
),
FieldCode::Sender => Field::Sender(
UniqueName::try_from(value)
.map(Into::into)
.map_err(D::Error::custom)?,
),
FieldCode::Signature => {
Field::Signature(Signature::try_from(value).map_err(D::Error::custom)?)
}
FieldCode::UnixFDs => Field::UnixFDs(u32::try_from(value).map_err(D::Error::custom)?),
})
}
}