#![allow(dead_code)]
use std::ffi::CStr;
use std::os::raw::{c_char, c_void};
use super::dbus::*;
pub(super) enum Variant<'a> {
Str(&'a CStr),
ObjectPath(&'a CStr),
Bool(bool),
Int32(i32),
UInt32(u32),
Pixmap {
width: i32,
height: i32,
argb: &'a [u8],
},
ToolTip { title: &'a CStr, body: &'a CStr },
}
pub(super) unsafe fn append_str(d: &DBus, it: *mut DBusMessageIter, s: &CStr) {
let p = s.as_ptr();
unsafe {
(d.dbus_message_iter_append_basic)(
it,
DBUS_TYPE_STRING,
&p as *const *const c_char as *const c_void,
);
}
}
pub(super) unsafe fn append_object_path(d: &DBus, it: *mut DBusMessageIter, s: &CStr) {
let p = s.as_ptr();
unsafe {
(d.dbus_message_iter_append_basic)(
it,
DBUS_TYPE_OBJECT_PATH,
&p as *const *const c_char as *const c_void,
);
}
}
pub(super) unsafe fn append_i32(d: &DBus, it: *mut DBusMessageIter, v: i32) {
unsafe {
(d.dbus_message_iter_append_basic)(it, DBUS_TYPE_INT32, &v as *const i32 as *const c_void);
}
}
pub(super) unsafe fn append_u32(d: &DBus, it: *mut DBusMessageIter, v: u32) {
unsafe {
(d.dbus_message_iter_append_basic)(it, DBUS_TYPE_UINT32, &v as *const u32 as *const c_void);
}
}
pub(super) unsafe fn append_bool(d: &DBus, it: *mut DBusMessageIter, v: bool) {
let b: DBusBool = if v { TRUE } else { FALSE };
unsafe {
(d.dbus_message_iter_append_basic)(
it,
DBUS_TYPE_BOOLEAN,
&b as *const DBusBool as *const c_void,
);
}
}
pub(super) unsafe fn append_pixmap(
d: &DBus,
it: *mut DBusMessageIter,
width: i32,
height: i32,
argb: &[u8],
) {
let mut arr = DBusMessageIter::uninit();
unsafe {
(d.dbus_message_iter_open_container)(it, DBUS_TYPE_ARRAY, c"(iiay)".as_ptr(), &mut arr);
let mut st = DBusMessageIter::uninit();
(d.dbus_message_iter_open_container)(&mut arr, DBUS_TYPE_STRUCT, std::ptr::null(), &mut st);
append_i32(d, &mut st, width);
append_i32(d, &mut st, height);
let mut bytes = DBusMessageIter::uninit();
(d.dbus_message_iter_open_container)(&mut st, DBUS_TYPE_ARRAY, c"y".as_ptr(), &mut bytes);
let ptr = argb.as_ptr();
(d.dbus_message_iter_append_fixed_array)(
&mut bytes,
DBUS_TYPE_BYTE,
&ptr as *const *const u8 as *const c_void,
argb.len() as std::os::raw::c_int,
);
(d.dbus_message_iter_close_container)(&mut st, &mut bytes);
(d.dbus_message_iter_close_container)(&mut arr, &mut st);
(d.dbus_message_iter_close_container)(it, &mut arr);
}
}
unsafe fn append_empty_array(d: &DBus, it: *mut DBusMessageIter, element_sig: &CStr) {
let mut arr = DBusMessageIter::uninit();
unsafe {
(d.dbus_message_iter_open_container)(it, DBUS_TYPE_ARRAY, element_sig.as_ptr(), &mut arr);
(d.dbus_message_iter_close_container)(it, &mut arr);
}
}
pub(super) unsafe fn append_variant(d: &DBus, it: *mut DBusMessageIter, value: &Variant) {
let sig: &CStr = match value {
Variant::Str(_) => c"s",
Variant::ObjectPath(_) => c"o",
Variant::Bool(_) => c"b",
Variant::Int32(_) => c"i",
Variant::UInt32(_) => c"u",
Variant::Pixmap { .. } => c"a(iiay)",
Variant::ToolTip { .. } => c"(sa(iiay)ss)",
};
let mut var = DBusMessageIter::uninit();
unsafe {
(d.dbus_message_iter_open_container)(it, DBUS_TYPE_VARIANT, sig.as_ptr(), &mut var);
match value {
Variant::Str(s) => append_str(d, &mut var, s),
Variant::ObjectPath(s) => append_object_path(d, &mut var, s),
Variant::Bool(b) => append_bool(d, &mut var, *b),
Variant::Int32(n) => append_i32(d, &mut var, *n),
Variant::UInt32(n) => append_u32(d, &mut var, *n),
Variant::Pixmap {
width,
height,
argb,
} => append_pixmap(d, &mut var, *width, *height, argb),
Variant::ToolTip { title, body } => {
let mut st = DBusMessageIter::uninit();
(d.dbus_message_iter_open_container)(
&mut var,
DBUS_TYPE_STRUCT,
std::ptr::null(),
&mut st,
);
append_str(d, &mut st, c""); append_empty_array(d, &mut st, c"(iiay)"); append_str(d, &mut st, title);
append_str(d, &mut st, body);
(d.dbus_message_iter_close_container)(&mut var, &mut st);
}
}
(d.dbus_message_iter_close_container)(it, &mut var);
}
}
pub(super) unsafe fn append_dict_entry(
d: &DBus,
array: *mut DBusMessageIter,
key: &CStr,
value: &Variant,
) {
let mut entry = DBusMessageIter::uninit();
unsafe {
(d.dbus_message_iter_open_container)(
array,
DBUS_TYPE_DICT_ENTRY,
std::ptr::null(),
&mut entry,
);
append_str(d, &mut entry, key);
append_variant(d, &mut entry, value);
(d.dbus_message_iter_close_container)(array, &mut entry);
}
}
pub(super) unsafe fn read_leading_strings(
d: &DBus,
msg: *mut DBusMessage,
max: usize,
) -> Vec<String> {
let mut it = DBusMessageIter::uninit();
let mut out = Vec::new();
unsafe {
if (d.dbus_message_iter_init)(msg, &mut it) == FALSE {
return out;
}
while out.len() < max {
let ty = (d.dbus_message_iter_get_arg_type)(&mut it);
if ty != DBUS_TYPE_STRING && ty != DBUS_TYPE_OBJECT_PATH {
break;
}
let mut p: *const c_char = std::ptr::null();
(d.dbus_message_iter_get_basic)(&mut it, &mut p as *mut *const c_char as *mut c_void);
if p.is_null() {
break;
}
out.push(CStr::from_ptr(p).to_string_lossy().into_owned());
if (d.dbus_message_iter_next)(&mut it) == FALSE {
break;
}
}
}
out
}
pub(super) unsafe fn iter_init(d: &DBus, msg: *mut DBusMessage) -> DBusMessageIter {
let mut it = DBusMessageIter::uninit();
unsafe { (d.dbus_message_iter_init)(msg, &mut it) };
it
}
pub(super) unsafe fn arg_type(d: &DBus, it: *mut DBusMessageIter) -> std::os::raw::c_int {
unsafe { (d.dbus_message_iter_get_arg_type)(it) }
}
pub(super) unsafe fn advance(d: &DBus, it: *mut DBusMessageIter) -> bool {
unsafe { (d.dbus_message_iter_next)(it) != FALSE }
}
pub(super) unsafe fn read_i32(d: &DBus, it: *mut DBusMessageIter) -> Option<i32> {
unsafe {
if arg_type(d, it) != DBUS_TYPE_INT32 {
return None;
}
let mut v: i32 = 0;
(d.dbus_message_iter_get_basic)(it, &mut v as *mut i32 as *mut c_void);
Some(v)
}
}
pub(super) unsafe fn read_u32(d: &DBus, it: *mut DBusMessageIter) -> Option<u32> {
unsafe {
if arg_type(d, it) != DBUS_TYPE_UINT32 {
return None;
}
let mut v: u32 = 0;
(d.dbus_message_iter_get_basic)(it, &mut v as *mut u32 as *mut c_void);
Some(v)
}
}
pub(super) unsafe fn read_string(d: &DBus, it: *mut DBusMessageIter) -> Option<String> {
unsafe {
let ty = arg_type(d, it);
if ty != DBUS_TYPE_STRING && ty != DBUS_TYPE_OBJECT_PATH {
return None;
}
let mut p: *const c_char = std::ptr::null();
(d.dbus_message_iter_get_basic)(it, &mut p as *mut *const c_char as *mut c_void);
if p.is_null() {
None
} else {
Some(CStr::from_ptr(p).to_string_lossy().into_owned())
}
}
}
pub(super) unsafe fn read_i32_array(d: &DBus, it: *mut DBusMessageIter) -> Vec<i32> {
let mut out = Vec::new();
unsafe {
if arg_type(d, it) != DBUS_TYPE_ARRAY {
return out;
}
let mut sub = DBusMessageIter::uninit();
(d.dbus_message_iter_recurse)(it, &mut sub);
while let Some(v) = read_i32(d, &mut sub) {
out.push(v);
if !advance(d, &mut sub) {
break;
}
}
}
out
}