Support for dynamic variants (fix #9)
This commit is contained in:
parent
408cda19bc
commit
73122deb8c
6 changed files with 378 additions and 10 deletions
|
@ -2,6 +2,7 @@ module ddbus.conv;
|
|||
|
||||
import ddbus.c_lib;
|
||||
import ddbus.util;
|
||||
import ddbus.thin;
|
||||
import std.string;
|
||||
import std.typecons;
|
||||
import std.range;
|
||||
|
@ -37,6 +38,48 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
|||
dbus_message_iter_open_container(iter, 'v', subSig, &sub);
|
||||
buildIter(&sub, arg.data);
|
||||
dbus_message_iter_close_container(iter, &sub);
|
||||
} else static if(is(T == DBusAny)) {
|
||||
DBusMessageIter subStore;
|
||||
DBusMessageIter* sub = &subStore;
|
||||
char[] sig = [cast(char) arg.type];
|
||||
if(arg.type == 'a')
|
||||
sig ~= arg.signature;
|
||||
else if(arg.type == 'r')
|
||||
sig = arg.signature;
|
||||
sig ~= '\0';
|
||||
if (!arg.explicitVariant)
|
||||
sub = iter;
|
||||
else
|
||||
dbus_message_iter_open_container(iter, 'v', sig.ptr, sub);
|
||||
if(arg.type == 's') {
|
||||
immutable(char)* cStr = arg.str.toStringz();
|
||||
dbus_message_iter_append_basic(sub,'s',&cStr);
|
||||
} else if(arg.type == 'b') {
|
||||
dbus_bool_t longerBool = arg.boolean; // dbus bools are ints
|
||||
dbus_message_iter_append_basic(sub,'b',&longerBool);
|
||||
} else if(dbus_type_is_basic(arg.type)) {
|
||||
dbus_message_iter_append_basic(sub,arg.type,&arg.int64);
|
||||
} else if(arg.type == 'a') {
|
||||
DBusMessageIter arr;
|
||||
dbus_message_iter_open_container(sub, 'a', sig[1 .. $].ptr, &arr);
|
||||
foreach(item; arg.array)
|
||||
buildIter(&arr, item);
|
||||
dbus_message_iter_close_container(sub, &arr);
|
||||
} else if(arg.type == 'r') {
|
||||
DBusMessageIter arr;
|
||||
dbus_message_iter_open_container(sub, 'r', null, &arr);
|
||||
foreach(item; arg.tuple)
|
||||
buildIter(&arr, item);
|
||||
dbus_message_iter_close_container(sub, &arr);
|
||||
} else if(arg.type == 'e') {
|
||||
DBusMessageIter entry;
|
||||
dbus_message_iter_open_container(sub, 'e', null, &entry);
|
||||
buildIter(&entry, arg.entry.key);
|
||||
buildIter(&entry, arg.entry.value);
|
||||
dbus_message_iter_close_container(sub, &entry);
|
||||
}
|
||||
if(arg.explicitVariant)
|
||||
dbus_message_iter_close_container(iter, sub);
|
||||
} else static if(is(T == DictionaryEntry!(K, V), K, V)) {
|
||||
DBusMessageIter sub;
|
||||
dbus_message_iter_open_container(iter, 'e', null, &sub);
|
||||
|
@ -56,6 +99,8 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
|||
DBusMessageIter sub;
|
||||
dbus_message_iter_recurse(iter, &sub);
|
||||
ret = readIter!T(&sub);
|
||||
static if(is(T == DBusAny))
|
||||
ret.explicitVariant = true;
|
||||
dbus_message_iter_next(iter);
|
||||
return ret;
|
||||
}
|
||||
|
@ -64,7 +109,7 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
|||
assert(dbus_message_iter_get_arg_type(iter) == 'r');
|
||||
} else static if(is(T == DictionaryEntry!(K1, V1), K1, V1)) {
|
||||
assert(dbus_message_iter_get_arg_type(iter) == 'e');
|
||||
} else {
|
||||
} else static if(!is(T == DBusAny)) {
|
||||
assert(dbus_message_iter_get_arg_type(iter) == typeCode!T());
|
||||
}
|
||||
static if(is(T==string)) {
|
||||
|
@ -102,6 +147,44 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
|||
auto entry = readIter!(DictionaryEntry!(KeyType!T, ValueType!T))(&sub);
|
||||
ret[entry.key] = entry.value;
|
||||
}
|
||||
} else static if(is(T == DBusAny)) {
|
||||
ret.type = dbus_message_iter_get_arg_type(iter);
|
||||
ret.explicitVariant = false;
|
||||
if(ret.type == 's') {
|
||||
const(char)* cStr;
|
||||
dbus_message_iter_get_basic(iter, &cStr);
|
||||
ret.str = cStr.fromStringz().idup; // copy string
|
||||
} else if(ret.type == 'b') {
|
||||
dbus_bool_t longerBool;
|
||||
dbus_message_iter_get_basic(iter, &longerBool);
|
||||
ret.boolean = cast(bool)longerBool;
|
||||
} else if(dbus_type_is_basic(ret.type)) {
|
||||
dbus_message_iter_get_basic(iter, &ret.int64);
|
||||
} else if(ret.type == 'a') {
|
||||
DBusMessageIter sub;
|
||||
dbus_message_iter_recurse(iter, &sub);
|
||||
auto sig = dbus_message_iter_get_signature(&sub);
|
||||
ret.signature = sig.fromStringz.dup;
|
||||
dbus_free(sig);
|
||||
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
||||
ret.array ~= readIter!DBusAny(&sub);
|
||||
}
|
||||
} else if(ret.type == 'r') {
|
||||
auto sig = dbus_message_iter_get_signature(iter);
|
||||
ret.signature = sig.fromStringz.dup;
|
||||
dbus_free(sig);
|
||||
DBusMessageIter sub;
|
||||
dbus_message_iter_recurse(iter, &sub);
|
||||
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
||||
ret.tuple ~= readIter!DBusAny(&sub);
|
||||
}
|
||||
} else if(ret.type == 'e') {
|
||||
DBusMessageIter sub;
|
||||
dbus_message_iter_recurse(iter, &sub);
|
||||
ret.entry = new DictionaryEntry!(DBusAny, DBusAny);
|
||||
ret.entry.key = readIter!DBusAny(&sub);
|
||||
ret.entry.value = readIter!DBusAny(&sub);
|
||||
}
|
||||
} else static if(basicDBus!T) {
|
||||
dbus_message_iter_get_basic(iter, &ret);
|
||||
}
|
||||
|
@ -123,9 +206,22 @@ unittest {
|
|||
bool[] emptyB;
|
||||
string[string] map;
|
||||
map["hello"] = "world";
|
||||
auto args = tuple(5,true,"wow",var(5.9),[6,5],tuple(6.2,4,[["lol"]],emptyB,var([4,2])),map);
|
||||
DBusAny anyVar = DBusAny(cast(ulong) 1561);
|
||||
anyVar.type.assertEqual('t');
|
||||
anyVar.uint64.assertEqual(1561);
|
||||
anyVar.explicitVariant.assertEqual(false);
|
||||
auto tupleMember = DBusAny(tuple(Variant!int(45), Variant!ushort(5), 32, [1, 2], tuple(variant(4), 5), map));
|
||||
DBusAny complexVar = DBusAny(variant([
|
||||
"hello world": variant(DBusAny(1337)),
|
||||
"array value": variant(DBusAny([42, 64])),
|
||||
"tuple value": variant(tupleMember)
|
||||
]));
|
||||
complexVar.type.assertEqual('a');
|
||||
complexVar.signature.assertEqual("{sv}".dup);
|
||||
tupleMember.signature.assertEqual("(vviai(vi)a{ss})");
|
||||
auto args = tuple(5,true,"wow",var(5.9),[6,5],tuple(6.2,4,[["lol"]],emptyB,var([4,2])),map,anyVar,complexVar);
|
||||
msg.build(args.expand);
|
||||
msg.signature().assertEqual("ibsvai(diaasabv)a{ss}");
|
||||
msg.signature().assertEqual("ibsvai(diaasabv)a{ss}tv");
|
||||
msg.readTuple!(typeof(args))().assertEqual(args);
|
||||
DBusMessageIter iter;
|
||||
dbus_message_iter_init(msg.msg, &iter);
|
||||
|
@ -136,4 +232,6 @@ unittest {
|
|||
readIter!(int[])(&iter).assertEqual([6,5]);
|
||||
readIter!(Tuple!(double,int,string[][],bool[],Variant!(int[])))(&iter).assertEqual(tuple(6.2,4,[["lol"]],emptyB,var([4,2])));
|
||||
readIter!(string[string])(&iter).assertEqual(["hello": "world"]);
|
||||
readIter!DBusAny(&iter).assertEqual(anyVar);
|
||||
readIter!DBusAny(&iter).assertEqual(complexVar);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue