use { crate::{ dbus::{ DbusError, DbusType, DynamicType, Formatter, Parser, TY_ARRAY, TY_BOOLEAN, TY_BYTE, TY_DOUBLE, TY_INT16, TY_INT32, TY_INT64, TY_OBJECT_PATH, TY_SIGNATURE, TY_STRING, TY_UINT16, TY_UINT32, TY_UINT64, TY_UNIX_FD, TY_VARIANT, }, utils::buf::DynamicBuf, }, std::{borrow::Cow, ops::Deref, rc::Rc}, uapi::{OwnedFd, Packed, Pod}, }; macro_rules! consume_signature_body { ($s:expr, $ty:expr) => {{ if $s.is_empty() { return Err(DbusError::EmptySignature); } if $s[0] != $ty { return Err(DbusError::InvalidSignatureType); } *$s = &(*$s)[1..]; }}; } macro_rules! signature { ($ty:expr) => { fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> { consume_signature_body!(s, $ty); Ok(()) } fn write_signature(w: &mut Vec) { w.push(TY_BYTE); } }; } unsafe impl<'a> DbusType<'a> for u8 { const ALIGNMENT: usize = 1; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_BYTE); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_pod() } } #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(transparent)] pub struct Bool(u32); pub const FALSE: Bool = Bool(0); pub const TRUE: Bool = Bool(1); unsafe impl Pod for Bool {} unsafe impl Packed for Bool {} unsafe impl<'a> DbusType<'a> for Bool { const ALIGNMENT: usize = 4; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_BOOLEAN); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_bool() } } unsafe impl<'a> DbusType<'a> for i16 { const ALIGNMENT: usize = 2; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_INT16); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_pod() } } unsafe impl<'a> DbusType<'a> for u16 { const ALIGNMENT: usize = 2; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_UINT16); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_pod() } } unsafe impl<'a> DbusType<'a> for i32 { const ALIGNMENT: usize = 4; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_INT32); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_pod() } } unsafe impl<'a> DbusType<'a> for u32 { const ALIGNMENT: usize = 4; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_UINT32); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_pod() } } unsafe impl<'a> DbusType<'a> for i64 { const ALIGNMENT: usize = 8; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_INT64); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_pod() } } unsafe impl<'a> DbusType<'a> for u64 { const ALIGNMENT: usize = 8; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_UINT64); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_pod() } } unsafe impl<'a> DbusType<'a> for f64 { const ALIGNMENT: usize = 8; const IS_POD: bool = true; type Generic<'b> = Self; signature!(TY_DOUBLE); fn marshal(&self, fmt: &mut Formatter) { fmt.write_packed(&self.to_bits()); } fn unmarshal(parser: &mut Parser<'a>) -> Result { Ok(f64::from_bits(parser.read_pod()?)) } } unsafe impl<'a> DbusType<'a> for Cow<'a, str> { const ALIGNMENT: usize = 4; const IS_POD: bool = false; type Generic<'b> = Cow<'b, str>; signature!(TY_STRING); fn marshal(&self, fmt: &mut Formatter) { fmt.write_str(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_string() } } #[derive(Clone, Debug, Eq, PartialEq)] pub struct Signature<'a>(pub Cow<'a, str>); impl<'a> Deref for Signature<'a> { type Target = str; fn deref(&self) -> &Self::Target { &self.0 } } unsafe impl<'a> DbusType<'a> for Signature<'a> { const ALIGNMENT: usize = 1; const IS_POD: bool = false; type Generic<'b> = Signature<'b>; signature!(TY_SIGNATURE); fn marshal(&self, fmt: &mut Formatter) { fmt.write_signature(self.0.as_bytes()); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_signature() } } #[derive(Clone, Debug, Eq, PartialEq)] pub struct ObjectPath<'a>(pub Cow<'a, str>); impl<'a> Deref for ObjectPath<'a> { type Target = str; fn deref(&self) -> &Self::Target { &self.0 } } unsafe impl<'a> DbusType<'a> for ObjectPath<'a> { const ALIGNMENT: usize = 4; const IS_POD: bool = false; type Generic<'b> = ObjectPath<'b>; signature!(TY_OBJECT_PATH); fn marshal(&self, fmt: &mut Formatter) { fmt.write_str(&self.0); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_object_path() } } unsafe impl<'a> DbusType<'a> for Rc { const ALIGNMENT: usize = 4; const IS_POD: bool = false; type Generic<'b> = Self; signature!(TY_UNIX_FD); fn marshal(&self, fmt: &mut Formatter) { fmt.write_fd(self) } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_fd() } fn num_fds(&self) -> u32 { 1 } } unsafe impl<'a, T: DbusType<'a>> DbusType<'a> for Cow<'a, [T]> { const ALIGNMENT: usize = 4; const IS_POD: bool = false; type Generic<'b> = Cow<'b, [T::Generic<'b>]>; fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> { consume_signature_body!(s, TY_ARRAY); T::consume_signature(s) } fn write_signature(w: &mut Vec) { w.push(TY_ARRAY); T::write_signature(w); } fn marshal(&self, fmt: &mut Formatter) { fmt.write_array(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_array() } fn num_fds(&self) -> u32 { let mut res = 0; for t in self.deref() { res += t.num_fds(); } res } } #[derive(Clone, Debug, Eq, PartialEq)] pub struct DictEntry { pub key: K, pub value: V, } unsafe impl<'a, K: DbusType<'a>, V: DbusType<'a>> DbusType<'a> for DictEntry { const ALIGNMENT: usize = 8; const IS_POD: bool = false; type Generic<'b> = DictEntry, V::Generic<'b>>; fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> { consume_signature_body!(s, b'{'); K::consume_signature(s)?; V::consume_signature(s)?; consume_signature_body!(s, b'}'); Ok(()) } fn write_signature(w: &mut Vec) { w.push(b'{'); K::write_signature(w); V::write_signature(w); w.push(b'}'); } fn marshal(&self, fmt: &mut Formatter) { fmt.pad_to(8); self.key.marshal(fmt); self.value.marshal(fmt); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.align_to(8)?; Ok(Self { key: K::unmarshal(parser)?, value: V::unmarshal(parser)?, }) } } macro_rules! tuple { ($($p:ident),*) => { #[expect(non_snake_case)] unsafe impl<'a, $($p: DbusType<'a>),*> DbusType<'a> for ($($p,)*) { const ALIGNMENT: usize = 8; const IS_POD: bool = false; type Generic<'b> = ($($p::Generic<'b>,)*); fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> { consume_signature_body!(s, b'('); $( $p::consume_signature(s)?; )* consume_signature_body!(s, b')'); Ok(()) } fn write_signature(w: &mut Vec) { w.push(b'('); $( $p::write_signature(w); )* w.push(b')'); } fn marshal(&self, fmt: &mut Formatter) { let ($($p,)*) = self; fmt.pad_to(8); $( $p.marshal(fmt); )* } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.align_to(8)?; Ok(($($p::unmarshal(parser)?,)*)) } fn num_fds(&self) -> u32 { let mut res = 0; let ($($p,)*) = self; $( res += $p.num_fds(); )* res } } } } tuple!(A); tuple!(A, B); tuple!(A, B, C); tuple!(A, B, C, D); tuple!(A, B, C, D, E); tuple!(A, B, C, D, E, F); tuple!(A, B, C, D, E, F, G); tuple!(A, B, C, D, E, F, G, H); #[derive(Clone, Debug)] pub enum Variant<'a> { U8(u8), Bool(Bool), I16(i16), U16(u16), I32(i32), U32(u32), I64(i64), U64(u64), F64(f64), String(Cow<'a, str>), ObjectPath(ObjectPath<'a>), Signature(Signature<'a>), Variant(Box>), Fd(Rc), Array(DynamicType, Vec>), DictEntry(Box>, Box>), Struct(Vec>), } impl<'a> Variant<'a> { pub fn into_string(self) -> Result, DbusError> { match self { Variant::String(s) => Ok(s), _ => Err(DbusError::InvalidVariantType), } } pub fn into_object_path(self) -> Result, DbusError> { match self { Variant::ObjectPath(s) => Ok(s), _ => Err(DbusError::InvalidVariantType), } } pub fn into_signature(self) -> Result, DbusError> { match self { Variant::Signature(s) => Ok(s), _ => Err(DbusError::InvalidVariantType), } } pub fn into_u32(self) -> Result { match self { Variant::U32(s) => Ok(s), _ => Err(DbusError::InvalidVariantType), } } pub fn write_signature(&self, w: &mut DynamicBuf) { let c = match self { Variant::U8(..) => TY_BYTE, Variant::Bool(..) => TY_BOOLEAN, Variant::I16(..) => TY_INT16, Variant::U16(..) => TY_UINT16, Variant::I32(..) => TY_INT32, Variant::U32(..) => TY_UINT32, Variant::I64(..) => TY_INT64, Variant::U64(..) => TY_UINT64, Variant::F64(..) => TY_DOUBLE, Variant::String(..) => TY_STRING, Variant::ObjectPath(..) => TY_OBJECT_PATH, Variant::Signature(..) => TY_SIGNATURE, Variant::Variant(..) => TY_VARIANT, Variant::Fd(..) => TY_UNIX_FD, Variant::Array(el, _) => { w.push(TY_ARRAY); el.write_signature(w); return; } Variant::DictEntry(k, v) => { w.push(b'{'); k.write_signature(w); v.write_signature(w); w.push(b'}'); return; } Variant::Struct(f) => { w.push(b'('); for f in f { f.write_signature(w); } w.push(b')'); return; } }; w.push(c); } pub fn borrow<'b>(&'b self) -> Variant<'b> { match self { Variant::U8(v) => Variant::U8(*v), Variant::Bool(v) => Variant::Bool(*v), Variant::I16(v) => Variant::I16(*v), Variant::U16(v) => Variant::U16(*v), Variant::I32(v) => Variant::I32(*v), Variant::U32(v) => Variant::U32(*v), Variant::I64(v) => Variant::I64(*v), Variant::U64(v) => Variant::U64(*v), Variant::F64(v) => Variant::F64(*v), Variant::String(v) => Variant::String(v.deref().into()), Variant::ObjectPath(v) => Variant::ObjectPath(ObjectPath(v.0.deref().into())), Variant::Signature(v) => Variant::Signature(Signature(v.0.deref().into())), Variant::Variant(v) => Variant::Variant(Box::new(v.deref().borrow())), Variant::Fd(v) => Variant::Fd(v.clone()), Variant::Array(t, v) => { Variant::Array(t.clone(), v.iter().map(|v| v.borrow()).collect()) } Variant::DictEntry(k, v) => { Variant::DictEntry(Box::new(k.deref().borrow()), Box::new(v.deref().borrow())) } Variant::Struct(v) => Variant::Struct(v.iter().map(|v| v.borrow()).collect()), } } } unsafe impl<'a> DbusType<'a> for Variant<'a> { const ALIGNMENT: usize = 1; const IS_POD: bool = false; type Generic<'b> = Variant<'b>; signature!(TY_VARIANT); fn marshal(&self, fmt: &mut Formatter) { fmt.write_variant(self); } fn unmarshal(parser: &mut Parser<'a>) -> Result { parser.read_variant() } fn num_fds(&self) -> u32 { match self { Variant::U8(_) => 0, Variant::Bool(_) => 0, Variant::I16(_) => 0, Variant::U16(_) => 0, Variant::I32(_) => 0, Variant::U32(_) => 0, Variant::I64(_) => 0, Variant::U64(_) => 0, Variant::F64(_) => 0, Variant::String(_) => 0, Variant::ObjectPath(_) => 0, Variant::Signature(_) => 0, Variant::Variant(v) => v.num_fds(), Variant::Array(_, a) => a.iter().map(|e| e.num_fds()).sum(), Variant::DictEntry(k, v) => k.num_fds() + v.num_fds(), Variant::Struct(f) => f.iter().map(|f| f.num_fds()).sum(), Variant::Fd(_) => 1, } } }