Merge pull request #16 from thaven/fix/dictionary
Dictionary related improvements
This commit is contained in:
commit
56f90644ce
|
@ -27,11 +27,29 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
||||||
const(char)* subSig = (typeSig!(ElementType!T)()).toStringz();
|
const(char)* subSig = (typeSig!(ElementType!T)()).toStringz();
|
||||||
dbus_message_iter_open_container(iter, 'a', subSig, &sub);
|
dbus_message_iter_open_container(iter, 'a', subSig, &sub);
|
||||||
foreach(x; arg) {
|
foreach(x; arg) {
|
||||||
buildIter(&sub, x);
|
static if(isInstanceOf!(DictionaryEntry, typeof(x))) {
|
||||||
|
DBusMessageIter entry;
|
||||||
|
dbus_message_iter_open_container(&sub, 'e', null, &entry);
|
||||||
|
buildIter(&entry, x.key);
|
||||||
|
buildIter(&entry, x.value);
|
||||||
|
dbus_message_iter_close_container(&sub, &entry);
|
||||||
|
} else {
|
||||||
|
buildIter(&sub, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dbus_message_iter_close_container(iter, &sub);
|
dbus_message_iter_close_container(iter, &sub);
|
||||||
} else static if(isAssociativeArray!T) {
|
} else static if(isAssociativeArray!T) {
|
||||||
buildIter(iter, arg.byDictionaryEntries);
|
DBusMessageIter sub;
|
||||||
|
const(char)* subSig = typeSig!T[1..$].toStringz();
|
||||||
|
dbus_message_iter_open_container(iter, 'a', subSig, &sub);
|
||||||
|
foreach(k, v; arg) {
|
||||||
|
DBusMessageIter entry;
|
||||||
|
dbus_message_iter_open_container(&sub, 'e', null, &entry);
|
||||||
|
buildIter(&entry, k);
|
||||||
|
buildIter(&entry, v);
|
||||||
|
dbus_message_iter_close_container(&sub, &entry);
|
||||||
|
}
|
||||||
|
dbus_message_iter_close_container(iter, &sub);
|
||||||
} else static if(is(T == DBusAny) || is(T == Variant!DBusAny)) {
|
} else static if(is(T == DBusAny) || is(T == Variant!DBusAny)) {
|
||||||
static if(is(T == Variant!DBusAny)) {
|
static if(is(T == Variant!DBusAny)) {
|
||||||
auto val = arg.data;
|
auto val = arg.data;
|
||||||
|
@ -88,12 +106,6 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
||||||
dbus_message_iter_open_container(iter, 'v', subSig, &sub);
|
dbus_message_iter_open_container(iter, 'v', subSig, &sub);
|
||||||
buildIter(&sub, arg.data);
|
buildIter(&sub, arg.data);
|
||||||
dbus_message_iter_close_container(iter, &sub);
|
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);
|
|
||||||
buildIter(&sub, arg.key);
|
|
||||||
buildIter(&sub, arg.value);
|
|
||||||
dbus_message_iter_close_container(iter, &sub);
|
|
||||||
} else static if(basicDBus!T) {
|
} else static if(basicDBus!T) {
|
||||||
dbus_message_iter_append_basic(iter,typeCode!T,&arg);
|
dbus_message_iter_append_basic(iter,typeCode!T,&arg);
|
||||||
}
|
}
|
||||||
|
@ -136,17 +148,19 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
DBusMessageIter sub;
|
DBusMessageIter sub;
|
||||||
dbus_message_iter_recurse(iter, &sub);
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
readIterTuple!T(&sub, ret);
|
readIterTuple!T(&sub, ret);
|
||||||
} else static if(is(T == DictionaryEntry!(K, V), K, V)) {
|
|
||||||
DBusMessageIter sub;
|
|
||||||
dbus_message_iter_recurse(iter, &sub);
|
|
||||||
ret.key = readIter!K(&sub);
|
|
||||||
ret.value = readIter!V(&sub);
|
|
||||||
} else static if(is(T t : U[], U)) {
|
} else static if(is(T t : U[], U)) {
|
||||||
assert(dbus_message_iter_get_element_type(iter) == typeCode!U);
|
assert(dbus_message_iter_get_element_type(iter) == typeCode!U);
|
||||||
DBusMessageIter sub;
|
DBusMessageIter sub;
|
||||||
dbus_message_iter_recurse(iter, &sub);
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
||||||
ret ~= readIter!U(&sub);
|
static if(is(U == DictionaryEntry!(K,V), K, V)) {
|
||||||
|
DBusMessageIter entry;
|
||||||
|
dbus_message_iter_recurse(&sub, &entry);
|
||||||
|
ret ~= U(readIter!K(&entry), readIter!V(&entry));
|
||||||
|
dbus_message_iter_next(&sub);
|
||||||
|
} else {
|
||||||
|
ret ~= readIter!U(&sub);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else static if(isVariant!T) {
|
} else static if(isVariant!T) {
|
||||||
DBusMessageIter sub;
|
DBusMessageIter sub;
|
||||||
|
@ -156,8 +170,12 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
DBusMessageIter sub;
|
DBusMessageIter sub;
|
||||||
dbus_message_iter_recurse(iter, &sub);
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
||||||
auto entry = readIter!(DictionaryEntry!(KeyType!T, ValueType!T))(&sub);
|
DBusMessageIter entry;
|
||||||
ret[entry.key] = entry.value;
|
dbus_message_iter_recurse(&sub, &entry);
|
||||||
|
auto k = readIter!(KeyType!T)(&entry);
|
||||||
|
auto v = readIter!(ValueType!T)(&entry);
|
||||||
|
ret[k] = v;
|
||||||
|
dbus_message_iter_next(&sub);
|
||||||
}
|
}
|
||||||
} else static if(is(T == DBusAny)) {
|
} else static if(is(T == DBusAny)) {
|
||||||
ret.type = dbus_message_iter_get_arg_type(iter);
|
ret.type = dbus_message_iter_get_arg_type(iter);
|
||||||
|
@ -251,7 +269,15 @@ unittest {
|
||||||
readIter!double(&iter).assertEqual(5.9);
|
readIter!double(&iter).assertEqual(5.9);
|
||||||
readIter!(int[])(&iter).assertEqual([6,5]);
|
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!(Tuple!(double,int,string[][],bool[],Variant!(int[])))(&iter).assertEqual(tuple(6.2,4,[["lol"]],emptyB,var([4,2])));
|
||||||
|
|
||||||
|
// There are two ways to read a dictionary, so duplicate the iterator to test both.
|
||||||
|
auto iter2 = iter;
|
||||||
readIter!(string[string])(&iter).assertEqual(["hello": "world"]);
|
readIter!(string[string])(&iter).assertEqual(["hello": "world"]);
|
||||||
|
auto dict = readIter!(DictionaryEntry!(string,string)[])(&iter2);
|
||||||
|
dict.length.assertEqual(1);
|
||||||
|
dict[0].key.assertEqual("hello");
|
||||||
|
dict[0].value.assertEqual("world");
|
||||||
|
|
||||||
readIter!DBusAny(&iter).assertEqual(anyVar);
|
readIter!DBusAny(&iter).assertEqual(anyVar);
|
||||||
readIter!(Variant!DBusAny)(&iter).assertEqual(complexVar);
|
readIter!(Variant!DBusAny)(&iter).assertEqual(complexVar);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,11 +59,13 @@ template canDBus(T) {
|
||||||
} 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) {
|
||||||
enum canDBus = canDBus!(ElementType!T);
|
static if(is(ElementType!T == DictionaryEntry!(K, V), K, V)) {
|
||||||
|
enum canDBus = basicDBus!K && canDBus!V;
|
||||||
|
} else {
|
||||||
|
enum canDBus = canDBus!(ElementType!T);
|
||||||
|
}
|
||||||
} else static if(isAssociativeArray!T) {
|
} else static if(isAssociativeArray!T) {
|
||||||
enum canDBus = canDBus!(KeyType!T) && canDBus!(ValueType!T);
|
enum canDBus = basicDBus!(KeyType!T) && canDBus!(ValueType!T);
|
||||||
} else static if(is(T == DictionaryEntry!(K, V), K, V)) {
|
|
||||||
enum canDBus = canDBus!K && canDBus!V;
|
|
||||||
} else {
|
} else {
|
||||||
enum canDBus = false;
|
enum canDBus = false;
|
||||||
}
|
}
|
||||||
|
@ -110,8 +112,6 @@ string typeSig(T)() if(canDBus!T) {
|
||||||
}
|
}
|
||||||
sig ~= ")";
|
sig ~= ")";
|
||||||
return sig;
|
return sig;
|
||||||
} else static if(is(T == DictionaryEntry!(K, V), K, V)) {
|
|
||||||
return '{' ~ typeSig!K ~ typeSig!V ~ '}';
|
|
||||||
} else static if(isInputRange!T) {
|
} else static if(isInputRange!T) {
|
||||||
return "a" ~ typeSig!(ElementType!T)();
|
return "a" ~ typeSig!(ElementType!T)();
|
||||||
} else static if(isAssociativeArray!T) {
|
} else static if(isAssociativeArray!T) {
|
||||||
|
@ -119,6 +119,12 @@ string typeSig(T)() if(canDBus!T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string typeSig(T)() if(isInstanceOf!(DictionaryEntry, T)) {
|
||||||
|
alias typeof(T.key) K;
|
||||||
|
alias typeof(T.value) V;
|
||||||
|
return "{" ~ typeSig!K ~ typeSig!V ~ '}';
|
||||||
|
}
|
||||||
|
|
||||||
string[] typeSigReturn(T)() if(canDBus!T) {
|
string[] typeSigReturn(T)() if(canDBus!T) {
|
||||||
static if(is(T == Tuple!TS, TS...))
|
static if(is(T == Tuple!TS, TS...))
|
||||||
return typeSigArr!TS;
|
return typeSigArr!TS;
|
||||||
|
@ -149,6 +155,10 @@ int typeCode(T)() if(canDBus!T) {
|
||||||
return typeSig!T()[0];
|
return typeSig!T()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int typeCode(T)() if(isInstanceOf!(DictionaryEntry, T) && canDBus!(T[])) {
|
||||||
|
return 'e';
|
||||||
|
}
|
||||||
|
|
||||||
unittest {
|
unittest {
|
||||||
import dunit.toolkit;
|
import dunit.toolkit;
|
||||||
// basics
|
// basics
|
||||||
|
@ -165,7 +175,7 @@ unittest {
|
||||||
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
||||||
// dictionaries
|
// dictionaries
|
||||||
typeSig!(int[string]).assertEqual("a{si}");
|
typeSig!(int[string]).assertEqual("a{si}");
|
||||||
typeSig!(DictionaryEntry!(string, int)).assertEqual("{si}");
|
typeSig!(DictionaryEntry!(string, int)[]).assertEqual("a{si}");
|
||||||
// multiple arguments
|
// multiple arguments
|
||||||
typeSigAll!(int,bool).assertEqual("ib");
|
typeSigAll!(int,bool).assertEqual("ib");
|
||||||
// type codes
|
// type codes
|
||||||
|
|
Loading…
Reference in a new issue