use super::{MessageIter, MessageRef};
use crate::bus;
use ffi::{c_char, c_int};
use std::ffi::CStr;
use utf8_cstr::Utf8CStr;
pub unsafe trait SdBusMessageDirect {
fn dbus_type() -> u8;
}
pub trait ToSdBusMessage {
fn to_message(&self, m: &mut MessageRef) -> crate::Result<()>;
}
pub trait FromSdBusMessage<'a> {
fn from_message(m: &'a mut MessageIter<'a>) -> crate::Result<Option<Self>>
where
Self: Sized;
}
impl<T: SdBusMessageDirect> ToSdBusMessage for T {
fn to_message(&self, m: &mut MessageRef) -> crate::Result<()> {
unsafe { m.append_basic_raw(Self::dbus_type(), self as *const _ as *const _) }
}
}
impl<'a, T: SdBusMessageDirect + 'a> FromSdBusMessage<'a> for T {
fn from_message(m: &'a mut MessageIter<'a>) -> crate::Result<Option<Self>>
where
Self: Sized,
{
let t = Self::dbus_type();
unsafe { m.read_basic_raw(t, |x| x) }
}
}
macro_rules! msg_basic {
($typ:ty : $dbus_type:expr) => {
unsafe impl SdBusMessageDirect for $typ {
fn dbus_type() -> u8 { $dbus_type }
}
};
($typ:ty : $dbus_type:expr , $($rest:tt)* ) => {
msg_basic!{$typ : $dbus_type}
msg_basic!{$($rest)*}
}
}
msg_basic! {
u8: b'y',
i16: b'n',
u16: b'q',
i32: b'i',
u32: b'u',
i64: b'x',
u64: b't',
f64: b'd'
}
impl ToSdBusMessage for bool {
fn to_message(&self, m: &mut MessageRef) -> crate::Result<()> {
let i: c_int = if *self { 1 } else { 0 };
unsafe { m.append_basic_raw(b'b', &i as *const _ as *const _) }?;
Ok(())
}
}
impl<'a> FromSdBusMessage<'a> for bool {
fn from_message(m: &mut MessageIter<'a>) -> crate::Result<Option<Self>>
where
Self: Sized,
{
unsafe { m.read_basic_raw(b'b', |x: c_int| x != 0) }
}
}
pub struct UnixFd(pub c_int);
impl ToSdBusMessage for UnixFd {
fn to_message(&self, m: &mut MessageRef) -> crate::Result<()> {
let i: c_int = self.0;
unsafe { m.append_basic_raw(b'h', &i as *const _ as *const _) }?;
Ok(())
}
}
impl<'a> FromSdBusMessage<'a> for UnixFd {
fn from_message(m: &'a mut MessageIter<'a>) -> crate::Result<Option<Self>>
where
Self: Sized,
{
unsafe { m.read_basic_raw(b'h', UnixFd) }
}
}
impl ToSdBusMessage for &bus::ObjectPath {
fn to_message(&self, m: &mut MessageRef) -> crate::Result<()> {
unsafe { m.append_basic_raw(b'o', self.as_ptr() as *const _) }?;
Ok(())
}
}
impl<'a> FromSdBusMessage<'a> for &'a bus::ObjectPath {
fn from_message(m: &'a mut MessageIter<'a>) -> crate::Result<Option<Self>>
where
Self: Sized,
{
unsafe {
m.read_basic_raw(b'o', |x: *const c_char| {
bus::ObjectPath::from_ptr_unchecked(x)
})
}
}
}
impl ToSdBusMessage for &Utf8CStr {
fn to_message(&self, m: &mut MessageRef) -> crate::Result<()> {
unsafe { m.append_basic_raw(b's', self.as_ptr() as *const _) }
}
}
impl<'a> FromSdBusMessage<'a> for &'a Utf8CStr {
fn from_message(m: &'a mut MessageIter<'a>) -> crate::Result<Option<Self>>
where
Self: Sized,
{
unsafe {
m.read_basic_raw(b's', |x: *const c_char| {
Utf8CStr::from_cstr_unchecked(CStr::from_ptr(x))
})
}
}
}