DBus iterator conversion to/from D types
This commit is contained in:
parent
fd19791f8d
commit
0e0e8971b4
92
source/ddbus/conv.d
Normal file
92
source/ddbus/conv.d
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
module ddbus.conv;
|
||||||
|
|
||||||
|
import ddbus.c_lib;
|
||||||
|
import ddbus.util;
|
||||||
|
import std.string;
|
||||||
|
import std.typecons;
|
||||||
|
import std.range;
|
||||||
|
|
||||||
|
void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
||||||
|
foreach(index, arg; args) {
|
||||||
|
alias TS[index] T;
|
||||||
|
static if(is(T == string)) {
|
||||||
|
immutable(char)* cStr = arg.toStringz();
|
||||||
|
dbus_message_iter_append_basic(iter,typeCode!T,&cStr);
|
||||||
|
} else static if(is(T==bool)) {
|
||||||
|
dbus_bool_t longerBool = arg; // dbus bools are ints
|
||||||
|
dbus_message_iter_append_basic(iter,typeCode!T,&longerBool);
|
||||||
|
} else static if(isTuple!T) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_open_container(iter, 'r', null, &sub);
|
||||||
|
buildIter(&sub, arg.expand);
|
||||||
|
dbus_message_iter_close_container(iter, &sub);
|
||||||
|
} else static if(isInputRange!T) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
const(char)* subSig = (typeSig!(ElementType!T)()).toStringz();
|
||||||
|
dbus_message_iter_open_container(iter, 'a', subSig, &sub);
|
||||||
|
foreach(x; arg) {
|
||||||
|
buildIter(&sub, x);
|
||||||
|
}
|
||||||
|
dbus_message_iter_close_container(iter, &sub);
|
||||||
|
} else static if(basicDBus!T) {
|
||||||
|
dbus_message_iter_append_basic(iter,typeCode!T,&arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
|
T ret;
|
||||||
|
static if(isTuple!T) {
|
||||||
|
assert(dbus_message_iter_get_arg_type(iter) == 'r');
|
||||||
|
} else {
|
||||||
|
assert(dbus_message_iter_get_arg_type(iter) == typeCode!T());
|
||||||
|
}
|
||||||
|
static if(is(T==string)) {
|
||||||
|
const(char)* cStr;
|
||||||
|
dbus_message_iter_get_basic(iter, &cStr);
|
||||||
|
ret = cStr.fromStringz().idup; // copy string
|
||||||
|
} else static if(is(T==bool)) {
|
||||||
|
dbus_bool_t longerBool;
|
||||||
|
dbus_message_iter_get_basic(iter, &longerBool);
|
||||||
|
ret = cast(bool)longerBool;
|
||||||
|
} else static if(isTuple!T) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
|
readIterTuple!T(&sub, ret);
|
||||||
|
} else static if(is(T t : U[], U)) {
|
||||||
|
assert(dbus_message_iter_get_element_type(iter) == typeCode!U);
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
|
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
||||||
|
ret ~= readIter!U(&sub);
|
||||||
|
}
|
||||||
|
} else static if(basicDBus!T) {
|
||||||
|
dbus_message_iter_get_basic(iter, &ret);
|
||||||
|
}
|
||||||
|
dbus_message_iter_next(iter);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void readIterTuple(Tup)(DBusMessageIter *iter, ref Tup tuple) if(isTuple!Tup && allCanDBus!(Tup.Types)) {
|
||||||
|
foreach(index, T; Tup.Types) {
|
||||||
|
tuple[index] = readIter!T(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
import dunit.toolkit;
|
||||||
|
import ddbus.thin;
|
||||||
|
Message msg = new Message("org.example.wow","/wut","org.test.iface","meth");
|
||||||
|
bool[] emptyB;
|
||||||
|
auto args = tuple(5,true,"wow",[6,5],tuple(6.2,4,[["lol"]],emptyB));
|
||||||
|
msg.build(args.expand);
|
||||||
|
msg.signature().assertEqual("ibsai(diaasab)");
|
||||||
|
msg.readTuple!(typeof(args))().assertEqual(args);
|
||||||
|
DBusMessageIter iter;
|
||||||
|
dbus_message_iter_init(msg.msg, &iter);
|
||||||
|
readIter!int(&iter).assertEqual(5);
|
||||||
|
readIter!bool(&iter).assertEqual(true);
|
||||||
|
readIter!string(&iter).assertEqual("wow");
|
||||||
|
readIter!(int[])(&iter).assertEqual([6,5]);
|
||||||
|
readIter!(Tuple!(double,int,string[][],bool[]))(&iter).assertEqual(tuple(6.2,4,[["lol"]],emptyB));
|
||||||
|
}
|
|
@ -1,9 +1,12 @@
|
||||||
module ddbus.thin;
|
module ddbus.thin;
|
||||||
|
|
||||||
import ddbus.c_lib;
|
import ddbus.c_lib;
|
||||||
|
import ddbus.conv;
|
||||||
|
import ddbus.util;
|
||||||
import std.string;
|
import std.string;
|
||||||
|
import std.typecons;
|
||||||
|
|
||||||
struct Message {
|
class Message {
|
||||||
this(string dest, string path, string iface, string method) {
|
this(string dest, string path, string iface, string method) {
|
||||||
msg = dbus_message_new_method_call(dest.toStringz(), path.toStringz(), iface.toStringz(), method.toStringz());
|
msg = dbus_message_new_method_call(dest.toStringz(), path.toStringz(), iface.toStringz(), method.toStringz());
|
||||||
}
|
}
|
||||||
|
@ -12,5 +15,44 @@ struct Message {
|
||||||
dbus_message_unref(msg);
|
dbus_message_unref(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void build(TS...)(TS args) if(allCanDBus!TS) {
|
||||||
|
DBusMessageIter iter;
|
||||||
|
dbus_message_iter_init_append(msg, &iter);
|
||||||
|
buildIter(&iter, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
T read(T)() if(canDBus!T) {
|
||||||
|
DBusMessageIter iter;
|
||||||
|
dbus_message_iter_init(msg, &iter);
|
||||||
|
return readIter!T(&iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tup readTuple(Tup)() if(isTuple!Tup && allCanDBus!(Tup.Types)) {
|
||||||
|
DBusMessageIter iter;
|
||||||
|
dbus_message_iter_init(msg, &iter);
|
||||||
|
Tup ret;
|
||||||
|
readIterTuple(&iter, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const(char)[] signature() {
|
||||||
|
const(char)* cSig = dbus_message_get_signature(msg);
|
||||||
|
return fromStringz(cSig);
|
||||||
|
}
|
||||||
|
|
||||||
DBusMessage *msg;
|
DBusMessage *msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class MessageBuilder {
|
||||||
|
// DBusMessageIter iter;
|
||||||
|
// // kept around for GC reasons, iterators need parent message.
|
||||||
|
// Message parent;
|
||||||
|
// this(Message msg) {
|
||||||
|
// parent = msg;
|
||||||
|
// dbus_message_iter_init(parent.msg, &iter);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void doBasic(int type, void *v) {
|
||||||
|
// dbus_message_iter_append_basic(&iter, type, v);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
@ -12,12 +12,19 @@ template allCanDBus(TS...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template canDBus(T) {
|
template basicDBus(T) {
|
||||||
static if(is(T == byte) || is(T == short) || is (T == ushort) || is (T == int)
|
static if(is(T == byte) || is(T == short) || is (T == ushort) || is (T == int)
|
||||||
|| is (T == uint) || is (T == long) || is (T == ulong)
|
|| is (T == uint) || is (T == long) || is (T == ulong)
|
||||||
|| is (T == double) || is (T == string) || is(T == bool)) {
|
|| is (T == double) || is (T == string) || is(T == bool)) {
|
||||||
|
enum basicDBus = true;
|
||||||
|
} else {
|
||||||
|
enum basicDBus = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template canDBus(T) {
|
||||||
|
static if(basicDBus!T) {
|
||||||
enum canDBus = true;
|
enum canDBus = true;
|
||||||
|
|
||||||
} else static if(isTuple!T) {
|
} else static if(isTuple!T) {
|
||||||
enum canDBus = allCanDBus!(T.Types);
|
enum canDBus = allCanDBus!(T.Types);
|
||||||
} else static if(isInputRange!T) {
|
} else static if(isInputRange!T) {
|
||||||
|
@ -77,6 +84,11 @@ string typeSigAll(TS...)() if(allCanDBus!TS) {
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int typeCode(T)() if(canDBus!T) {
|
||||||
|
string sig = typeSig!T();
|
||||||
|
return sig[0];
|
||||||
|
}
|
||||||
|
|
||||||
unittest {
|
unittest {
|
||||||
import dunit.toolkit;
|
import dunit.toolkit;
|
||||||
// basics
|
// basics
|
||||||
|
@ -91,6 +103,9 @@ unittest {
|
||||||
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
||||||
// multiple arguments
|
// multiple arguments
|
||||||
typeSigAll!(int,bool).assertEqual("ib");
|
typeSigAll!(int,bool).assertEqual("ib");
|
||||||
|
// type codes
|
||||||
|
typeCode!int().assertEqual(cast(int)('i'));
|
||||||
|
typeCode!bool().assertEqual(cast(int)('b'));
|
||||||
// ctfe-capable
|
// ctfe-capable
|
||||||
static string sig = typeSig!ulong();
|
static string sig = typeSig!ulong();
|
||||||
sig.assertEqual("t");
|
sig.assertEqual("t");
|
||||||
|
|
Loading…
Reference in a new issue