Fix various template instantiation errors

Some templates broke because canDBus!(DictionaryEntry!(K,V)) now returns false.
Also, associative arrays are now handled without using a DictionaryEntry type. This is a first step in eliminating DictionaryEntry.
This commit is contained in:
Harry T. Vennik 2017-06-18 17:43:19 +02:00
parent a6aa85ac74
commit 3fa88ee9f7
2 changed files with 53 additions and 18 deletions

View file

@ -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) {
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); 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,18 +148,20 @@ 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) {
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); ret ~= readIter!U(&sub);
} }
}
} else static if(isVariant!T) { } else static if(isVariant!T) {
DBusMessageIter sub; DBusMessageIter sub;
dbus_message_iter_recurse(iter, &sub); dbus_message_iter_recurse(iter, &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);
} }

View file

@ -112,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) {
@ -121,6 +119,13 @@ string typeSig(T)() if(canDBus!T) {
} }
} }
string typeSig(T)() if(isInstanceOf!(DictionaryEntry, T)) {
static if(is(T == DictionaryEntry!(K, V), K, V)) // need to get K and V somehow
return "{" ~ typeSig!K ~ typeSig!V ~ '}';
else
static assert (false, "DictionaryEntry always has a key type and value type, right?");
}
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 +154,10 @@ int typeCode(T)() if(canDBus!T) {
return sig[0]; return sig[0];
} }
int typeCode(T)() if(isInstanceOf!(DictionaryEntry, T) && canDBus!(T[])) {
return 'e';
}
unittest { unittest {
import dunit.toolkit; import dunit.toolkit;
// basics // basics