Added support for POD structs
Note: structs are deliberately considered last, because other stuff may be implemented as structs as well. So we need to take care of special cases before trying struct (de)serialization.
This commit is contained in:
parent
15ae9fec23
commit
6bce6cf649
|
@ -113,6 +113,11 @@ 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 == struct)) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_open_container(iter, 'r', null, &sub);
|
||||||
|
buildIter(&sub, arg.tupleof);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -265,6 +270,10 @@ T readIter(T)(DBusMessageIter *iter) if (!is(T == enum) && !isInstanceOf!(BitFla
|
||||||
ret.entry.key = readIter!DBusAny(&sub);
|
ret.entry.key = readIter!DBusAny(&sub);
|
||||||
ret.entry.value = readIter!DBusAny(&sub);
|
ret.entry.value = readIter!DBusAny(&sub);
|
||||||
}
|
}
|
||||||
|
} else static if(is(T == struct)) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
|
readIterStruct!T(&sub, ret);
|
||||||
} else static if(basicDBus!T) {
|
} else static if(basicDBus!T) {
|
||||||
dbus_message_iter_get_basic(iter, &ret);
|
dbus_message_iter_get_basic(iter, &ret);
|
||||||
}
|
}
|
||||||
|
@ -279,6 +288,13 @@ void readIterTuple(Tup)(DBusMessageIter *iter, ref Tup tuple) if(isTuple!Tup &&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void readIterStruct(S)(DBusMessageIter *iter, ref S s) if(is(S == struct) && allCanDBus!(Fields!S)) {
|
||||||
|
alias FieldNameTuple!S names;
|
||||||
|
foreach(index, T; Fields!S) {
|
||||||
|
__traits(getMember, s, names[index]) = readIter!T(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unittest {
|
unittest {
|
||||||
import dunit.toolkit;
|
import dunit.toolkit;
|
||||||
import ddbus.thin;
|
import ddbus.thin;
|
||||||
|
@ -355,3 +371,22 @@ unittest {
|
||||||
readIter!F(&iter).assertThrow!InvalidValueException();
|
readIter!F(&iter).assertThrow!InvalidValueException();
|
||||||
readIter!(BitFlags!F)(&iter2).assertThrow!InvalidValueException();
|
readIter!(BitFlags!F)(&iter2).assertThrow!InvalidValueException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
import dunit.toolkit;
|
||||||
|
import ddbus.thin;
|
||||||
|
|
||||||
|
struct S1 { int a; double b; string s; }
|
||||||
|
struct S2 { Variant!int c; string d; S1 e; uint f; }
|
||||||
|
|
||||||
|
Message msg = Message("org.example.wow", "/wut", "org.test.iface", "meth3");
|
||||||
|
|
||||||
|
enum testStruct = S2(variant(5), "blah", S1(-7, 63.5, "test"), 16);
|
||||||
|
msg.build(testStruct);
|
||||||
|
|
||||||
|
DBusMessageIter iter;
|
||||||
|
dbus_message_iter_init(msg.msg, &iter);
|
||||||
|
|
||||||
|
readIter!S2(&iter).assertEqual(testStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,8 @@ template canDBus(T) {
|
||||||
}
|
}
|
||||||
} else static if(isAssociativeArray!T) {
|
} else static if(isAssociativeArray!T) {
|
||||||
enum canDBus = basicDBus!(KeyType!T) && canDBus!(ValueType!T);
|
enum canDBus = basicDBus!(KeyType!T) && canDBus!(ValueType!T);
|
||||||
|
} else static if(is(T == struct) && !isInstanceOf!(DictionaryEntry, T)) {
|
||||||
|
enum canDBus = allCanDBus!(Fields!T);
|
||||||
} else {
|
} else {
|
||||||
enum canDBus = false;
|
enum canDBus = false;
|
||||||
}
|
}
|
||||||
|
@ -130,6 +132,13 @@ string typeSig(T)() if(canDBus!T) {
|
||||||
return "a" ~ typeSig!(ElementType!T)();
|
return "a" ~ typeSig!(ElementType!T)();
|
||||||
} else static if(isAssociativeArray!T) {
|
} else static if(isAssociativeArray!T) {
|
||||||
return "a{" ~ typeSig!(KeyType!T) ~ typeSig!(ValueType!T) ~ "}";
|
return "a{" ~ typeSig!(KeyType!T) ~ typeSig!(ValueType!T) ~ "}";
|
||||||
|
} else static if(is(T == struct)) {
|
||||||
|
string sig = "(";
|
||||||
|
foreach(i, S; Fields!T) {
|
||||||
|
sig ~= typeSig!S();
|
||||||
|
}
|
||||||
|
sig ~= ")";
|
||||||
|
return sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,10 +172,8 @@ string[] typeSigArr(TS...)() if(allCanDBus!TS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int typeCode(T)() if(canDBus!T) {
|
int typeCode(T)() if(canDBus!T) {
|
||||||
static if (isTuple!T)
|
int code = typeSig!T()[0];
|
||||||
return 'r';
|
return (code != '(') ? code : 'r';
|
||||||
else
|
|
||||||
return typeSig!T()[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int typeCode(T)() if(isInstanceOf!(DictionaryEntry, T) && canDBus!(T[])) {
|
int typeCode(T)() if(isInstanceOf!(DictionaryEntry, T) && canDBus!(T[])) {
|
||||||
|
@ -188,9 +195,14 @@ unittest {
|
||||||
// bit flags
|
// bit flags
|
||||||
enum F : uint { a = 1, b = 2, c = 4 }
|
enum F : uint { a = 1, b = 2, c = 4 }
|
||||||
typeSig!(BitFlags!F)().assertEqual(typeSig!uint());
|
typeSig!(BitFlags!F)().assertEqual(typeSig!uint());
|
||||||
// structs
|
// tuples (represented as structs in DBus)
|
||||||
typeSig!(Tuple!(int,string,string)).assertEqual("(iss)");
|
typeSig!(Tuple!(int,string,string)).assertEqual("(iss)");
|
||||||
typeSig!(Tuple!(int,string,Variant!int,Tuple!(int,"k",double,"x"))).assertEqual("(isv(id))");
|
typeSig!(Tuple!(int,string,Variant!int,Tuple!(int,"k",double,"x"))).assertEqual("(isv(id))");
|
||||||
|
// structs
|
||||||
|
struct S1 { int a; double b; string s; }
|
||||||
|
typeSig!S1.assertEqual("(ids)");
|
||||||
|
struct S2 { Variant!int c; string d; S1 e; uint f; }
|
||||||
|
typeSig!S2.assertEqual("(vs(ids)u)");
|
||||||
// arrays
|
// arrays
|
||||||
typeSig!(int[]).assertEqual("ai");
|
typeSig!(int[]).assertEqual("ai");
|
||||||
typeSig!(Variant!int[]).assertEqual("av");
|
typeSig!(Variant!int[]).assertEqual("av");
|
||||||
|
|
Loading…
Reference in a new issue