Merge pull request #8 from WebFreak001/maps
Support for maps/dictionaries
This commit is contained in:
commit
408cda19bc
|
@ -5,6 +5,7 @@ import ddbus.util;
|
||||||
import std.string;
|
import std.string;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import std.range;
|
import std.range;
|
||||||
|
import std.traits;
|
||||||
|
|
||||||
void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
||||||
foreach(index, arg; args) {
|
foreach(index, arg; args) {
|
||||||
|
@ -28,12 +29,20 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
||||||
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) {
|
||||||
|
buildIter(iter, arg.byDictionaryEntries);
|
||||||
} else static if(isVariant!T) {
|
} else static if(isVariant!T) {
|
||||||
DBusMessageIter sub;
|
DBusMessageIter sub;
|
||||||
const(char)* subSig = typeSig!(VariantType!T).toStringz();
|
const(char)* subSig = typeSig!(VariantType!T).toStringz();
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +62,8 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
}
|
}
|
||||||
static if(isTuple!T) {
|
static if(isTuple!T) {
|
||||||
assert(dbus_message_iter_get_arg_type(iter) == 'r');
|
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 {
|
||||||
assert(dbus_message_iter_get_arg_type(iter) == typeCode!T());
|
assert(dbus_message_iter_get_arg_type(iter) == typeCode!T());
|
||||||
}
|
}
|
||||||
|
@ -68,6 +79,11 @@ 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;
|
||||||
|
@ -79,6 +95,13 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
DBusMessageIter sub;
|
DBusMessageIter sub;
|
||||||
dbus_message_iter_recurse(iter, &sub);
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
ret.data = readIter!(VariantType!T)(&sub);
|
ret.data = readIter!(VariantType!T)(&sub);
|
||||||
|
} else static if(isAssociativeArray!T) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
|
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
||||||
|
auto entry = readIter!(DictionaryEntry!(KeyType!T, ValueType!T))(&sub);
|
||||||
|
ret[entry.key] = entry.value;
|
||||||
|
}
|
||||||
} else static if(basicDBus!T) {
|
} else static if(basicDBus!T) {
|
||||||
dbus_message_iter_get_basic(iter, &ret);
|
dbus_message_iter_get_basic(iter, &ret);
|
||||||
}
|
}
|
||||||
|
@ -98,9 +121,11 @@ unittest {
|
||||||
Variant!T var(T)(T data){ return Variant!T(data); }
|
Variant!T var(T)(T data){ return Variant!T(data); }
|
||||||
Message msg = Message("org.example.wow","/wut","org.test.iface","meth");
|
Message msg = Message("org.example.wow","/wut","org.test.iface","meth");
|
||||||
bool[] emptyB;
|
bool[] emptyB;
|
||||||
auto args = tuple(5,true,"wow",var(5.9),[6,5],tuple(6.2,4,[["lol"]],emptyB,var([4,2])));
|
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);
|
||||||
msg.build(args.expand);
|
msg.build(args.expand);
|
||||||
msg.signature().assertEqual("ibsvai(diaasabv)");
|
msg.signature().assertEqual("ibsvai(diaasabv)a{ss}");
|
||||||
msg.readTuple!(typeof(args))().assertEqual(args);
|
msg.readTuple!(typeof(args))().assertEqual(args);
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
dbus_message_iter_init(msg.msg, &iter);
|
dbus_message_iter_init(msg.msg, &iter);
|
||||||
|
@ -110,4 +135,5 @@ 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])));
|
||||||
|
readIter!(string[string])(&iter).assertEqual(["hello": "world"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ void registerMethods(T : Object)(MessageRouter router, string path, string iface
|
||||||
unittest {
|
unittest {
|
||||||
import dunit.toolkit;
|
import dunit.toolkit;
|
||||||
class Tester {
|
class Tester {
|
||||||
int lol(int x, string s) {return 5;}
|
int lol(int x, string s, string[string] map) {return 5;}
|
||||||
void wat() {}
|
void wat() {}
|
||||||
@SignalMethod
|
@SignalMethod
|
||||||
void signalRecv() {}
|
void signalRecv() {}
|
||||||
|
@ -91,6 +91,6 @@ unittest {
|
||||||
patt.signal = false;
|
patt.signal = false;
|
||||||
router.callTable.assertHasKey(patt);
|
router.callTable.assertHasKey(patt);
|
||||||
auto res = router.callTable[patt];
|
auto res = router.callTable[patt];
|
||||||
res.argSig.assertEqual(["i","s"]);
|
res.argSig.assertEqual(["i","s", "a{ss}"]);
|
||||||
res.retSig.assertEqual(["i"]);
|
res.retSig.assertEqual(["i"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,17 @@ import std.typecons;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
|
||||||
|
struct DictionaryEntry(K, V) {
|
||||||
|
K key;
|
||||||
|
V value;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto byDictionaryEntries(K, V)(V[K] aa) {
|
||||||
|
import std.algorithm : map;
|
||||||
|
|
||||||
|
return aa.byKeyValue.map!(pair => DictionaryEntry!(K, V)(pair.key, pair.value));
|
||||||
|
}
|
||||||
|
|
||||||
template isVariant(T) {
|
template isVariant(T) {
|
||||||
static if(isBasicType!T || isInputRange!T) {
|
static if(isBasicType!T || isInputRange!T) {
|
||||||
enum isVariant = false;
|
enum isVariant = false;
|
||||||
|
@ -49,6 +60,10 @@ template canDBus(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);
|
enum canDBus = canDBus!(ElementType!T);
|
||||||
|
} else static if(isAssociativeArray!T) {
|
||||||
|
enum canDBus = canDBus!(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;
|
||||||
}
|
}
|
||||||
|
@ -59,8 +74,8 @@ unittest {
|
||||||
(canDBus!(int[])).assertTrue();
|
(canDBus!(int[])).assertTrue();
|
||||||
(allCanDBus!(int,string,bool)).assertTrue();
|
(allCanDBus!(int,string,bool)).assertTrue();
|
||||||
(canDBus!(Tuple!(int[],bool,Variant!short))).assertTrue();
|
(canDBus!(Tuple!(int[],bool,Variant!short))).assertTrue();
|
||||||
(canDBus!(Tuple!(int[],int[string]))).assertFalse();
|
(canDBus!(Tuple!(int[],int[string]))).assertTrue();
|
||||||
(canDBus!(int[string])).assertFalse();
|
(canDBus!(int[string])).assertTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
string typeSig(T)() if(canDBus!T) {
|
string typeSig(T)() if(canDBus!T) {
|
||||||
|
@ -93,8 +108,12 @@ 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) {
|
||||||
|
return "a{" ~ typeSig!(KeyType!T) ~ typeSig!(ValueType!T) ~ "}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +159,9 @@ unittest {
|
||||||
typeSig!(int[]).assertEqual("ai");
|
typeSig!(int[]).assertEqual("ai");
|
||||||
typeSig!(Variant!int[]).assertEqual("av");
|
typeSig!(Variant!int[]).assertEqual("av");
|
||||||
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
||||||
|
// dictionaries
|
||||||
|
typeSig!(int[string]).assertEqual("a{si}");
|
||||||
|
typeSig!(DictionaryEntry!(string, int)).assertEqual("{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