use super::utf8_cstr::Utf8CStr;
use std::ffi::CStr;
use super::{MessageRef, MessageIter};
use ffi::{c_int, c_char};
pub unsafe trait SdBusMessageDirect {
fn dbus_type() -> u8;
}
pub trait ToSdBusMessage {
fn to_message(&self, m: &mut MessageRef) -> ::Result<()>;
}
pub trait FromSdBusMessage<'a> {
fn from_message(m: &'a mut MessageIter<'a>) -> ::Result<Option<Self>>
where Self: Sized;
}
impl<T: SdBusMessageDirect> ToSdBusMessage for T {
fn to_message(&self, m: &mut MessageRef) -> ::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>) -> ::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) -> ::Result<()> {
let i : c_int = if *self { 1 } else { 0 };
try!(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>) -> ::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) -> ::Result<()> {
let i : c_int = self.0;
try!(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>) -> ::Result<Option<Self>>
where Self: Sized
{
unsafe { m.read_basic_raw(b'h', |x: c_int| UnixFd(x)) }
}
}
impl<'a> ToSdBusMessage for &'a super::ObjectPath {
fn to_message(&self, m: &mut MessageRef) -> ::Result<()> {
try!(unsafe { m.append_basic_raw(b'o', self.as_ptr() as *const _)});
Ok(())
}
}
impl<'a> FromSdBusMessage<'a> for &'a super::ObjectPath {
fn from_message(m: &'a mut MessageIter<'a>) -> ::Result<Option<Self>>
where Self: Sized
{
unsafe {m.read_basic_raw(b'o', |x: *const c_char| super::ObjectPath::from_ptr_unchecked(x))}
}
}
impl<'a> ToSdBusMessage for &'a Utf8CStr {
fn to_message(&self, m: &mut MessageRef) -> ::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>) -> ::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)))}
}
}