Merge pull request #2 from xentec/variant-2
Added basic variant type support
This commit is contained in:
commit
3a40dc6ab2
15
Readme.md
15
Readme.md
|
@ -42,6 +42,21 @@ auto name = obj.GetNameOwner("org.freedesktop.DBus").to!string();
|
||||||
obj.call!string("GetNameOwner","org.freedesktop.DBus");
|
obj.call!string("GetNameOwner","org.freedesktop.DBus");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Working with properties
|
||||||
|
|
||||||
|
```d
|
||||||
|
import ddbus;
|
||||||
|
Connection conn = connectToBus();
|
||||||
|
PathIface obj = new PathIface(conn, "org.freedesktop.secrets", "/org/freedesktop/secrets/collection/login", "org.freedesktop.DBus.Properties");
|
||||||
|
|
||||||
|
// read property
|
||||||
|
string loginLabel = obj.Get("org.freedesktop.Secret.Collection", "Label").to!string();
|
||||||
|
loginLabel = "Secret"~login;
|
||||||
|
// write it back (variant type requires variant() wrapper)
|
||||||
|
obj.Set("org.freedesktop.Secret.Collection", "Label", variant(loginLabel));
|
||||||
|
```
|
||||||
|
Setting read only properties results in a thrown `DBusException`.
|
||||||
|
|
||||||
## Server Interface
|
## Server Interface
|
||||||
|
|
||||||
You can register a delegate into a `MessageRouter` and a main loop in order to handle messages.
|
You can register a delegate into a `MessageRouter` and a main loop in order to handle messages.
|
||||||
|
|
|
@ -28,6 +28,12 @@ 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(isVariant!T) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
const(char)* subSig = typeSig!(VariantType!T).toStringz();
|
||||||
|
dbus_message_iter_open_container(iter, 'v', subSig, &sub);
|
||||||
|
buildIter(&sub, arg.data);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +42,15 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
||||||
|
|
||||||
T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
T ret;
|
T ret;
|
||||||
|
static if(!isVariant!T) {
|
||||||
|
if(dbus_message_iter_get_arg_type(iter) == 'v') {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
|
ret = readIter!T(&sub);
|
||||||
|
dbus_message_iter_next(iter);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
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 {
|
} else {
|
||||||
|
@ -60,6 +75,10 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
while(dbus_message_iter_get_arg_type(&sub) != 0) {
|
||||||
ret ~= readIter!U(&sub);
|
ret ~= readIter!U(&sub);
|
||||||
}
|
}
|
||||||
|
} else static if(isVariant!T) {
|
||||||
|
DBusMessageIter sub;
|
||||||
|
dbus_message_iter_recurse(iter, &sub);
|
||||||
|
ret.data = readIter!(VariantType!T)(&sub);
|
||||||
} else static if(basicDBus!T) {
|
} else static if(basicDBus!T) {
|
||||||
dbus_message_iter_get_basic(iter, &ret);
|
dbus_message_iter_get_basic(iter, &ret);
|
||||||
}
|
}
|
||||||
|
@ -76,17 +95,19 @@ void readIterTuple(Tup)(DBusMessageIter *iter, ref Tup tuple) if(isTuple!Tup &&
|
||||||
unittest {
|
unittest {
|
||||||
import dunit.toolkit;
|
import dunit.toolkit;
|
||||||
import ddbus.thin;
|
import ddbus.thin;
|
||||||
|
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",[6,5],tuple(6.2,4,[["lol"]],emptyB));
|
auto args = tuple(5,true,"wow",var(5.9),[6,5],tuple(6.2,4,[["lol"]],emptyB,var([4,2])));
|
||||||
msg.build(args.expand);
|
msg.build(args.expand);
|
||||||
msg.signature().assertEqual("ibsai(diaasab)");
|
msg.signature().assertEqual("ibsvai(diaasabv)");
|
||||||
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);
|
||||||
readIter!int(&iter).assertEqual(5);
|
readIter!int(&iter).assertEqual(5);
|
||||||
readIter!bool(&iter).assertEqual(true);
|
readIter!bool(&iter).assertEqual(true);
|
||||||
readIter!string(&iter).assertEqual("wow");
|
readIter!string(&iter).assertEqual("wow");
|
||||||
|
readIter!double(&iter).assertEqual(5.9);
|
||||||
readIter!(int[])(&iter).assertEqual([6,5]);
|
readIter!(int[])(&iter).assertEqual([6,5]);
|
||||||
readIter!(Tuple!(double,int,string[][],bool[]))(&iter).assertEqual(tuple(6.2,4,[["lol"]],emptyB));
|
readIter!(Tuple!(double,int,string[][],bool[],Variant!(int[])))(&iter).assertEqual(tuple(6.2,4,[["lol"]],emptyB,var([4,2])));
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,14 @@ T wrapErrors(T)(T delegate(DBusError *err) del) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Variant(T) {
|
||||||
|
T data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant!T variant(T)(T data) {
|
||||||
|
return Variant!T(data);
|
||||||
|
}
|
||||||
|
|
||||||
enum MessageType {
|
enum MessageType {
|
||||||
Invalid = 0,
|
Invalid = 0,
|
||||||
Call, Return, Error, Signal
|
Call, Return, Error, Signal
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
module ddbus.util;
|
module ddbus.util;
|
||||||
|
|
||||||
|
import ddbus.thin;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import std.range;
|
import std.range;
|
||||||
|
import std.traits;
|
||||||
|
|
||||||
|
template isVariant(T) {
|
||||||
|
static if(isBasicType!T || isInputRange!T) {
|
||||||
|
enum isVariant = false;
|
||||||
|
} else static if(__traits(compiles, TemplateOf!T)
|
||||||
|
&& __traits(isSame, TemplateOf!T, Variant)) {
|
||||||
|
enum isVariant = true;
|
||||||
|
} else {
|
||||||
|
enum isVariant = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template VariantType(T) {
|
||||||
|
alias VariantType = TemplateArgsOf!(T)[0];
|
||||||
|
}
|
||||||
|
|
||||||
template allCanDBus(TS...) {
|
template allCanDBus(TS...) {
|
||||||
static if (TS.length == 0) {
|
static if (TS.length == 0) {
|
||||||
|
@ -25,6 +43,8 @@ template basicDBus(T) {
|
||||||
template canDBus(T) {
|
template canDBus(T) {
|
||||||
static if(basicDBus!T) {
|
static if(basicDBus!T) {
|
||||||
enum canDBus = true;
|
enum canDBus = true;
|
||||||
|
} else static if(isVariant!T) {
|
||||||
|
enum canDBus = canDBus!(VariantType!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) {
|
||||||
|
@ -38,7 +58,7 @@ unittest {
|
||||||
(canDBus!int).assertTrue();
|
(canDBus!int).assertTrue();
|
||||||
(canDBus!(int[])).assertTrue();
|
(canDBus!(int[])).assertTrue();
|
||||||
(allCanDBus!(int,string,bool)).assertTrue();
|
(allCanDBus!(int,string,bool)).assertTrue();
|
||||||
(canDBus!(Tuple!(int[],bool))).assertTrue();
|
(canDBus!(Tuple!(int[],bool,Variant!short))).assertTrue();
|
||||||
(canDBus!(Tuple!(int[],int[string]))).assertFalse();
|
(canDBus!(Tuple!(int[],int[string]))).assertFalse();
|
||||||
(canDBus!(int[string])).assertFalse();
|
(canDBus!(int[string])).assertFalse();
|
||||||
}
|
}
|
||||||
|
@ -64,8 +84,8 @@ string typeSig(T)() if(canDBus!T) {
|
||||||
return "d";
|
return "d";
|
||||||
} else static if(is(T == string)) {
|
} else static if(is(T == string)) {
|
||||||
return "s";
|
return "s";
|
||||||
} else static if(is(T == void)) {
|
} else static if(isVariant!T) {
|
||||||
return "";
|
return "v";
|
||||||
} else static if(isTuple!T) {
|
} else static if(isTuple!T) {
|
||||||
string sig = "(";
|
string sig = "(";
|
||||||
foreach(i, S; T.Types) {
|
foreach(i, S; T.Types) {
|
||||||
|
@ -105,11 +125,13 @@ unittest {
|
||||||
typeSig!int().assertEqual("i");
|
typeSig!int().assertEqual("i");
|
||||||
typeSig!bool().assertEqual("b");
|
typeSig!bool().assertEqual("b");
|
||||||
typeSig!string().assertEqual("s");
|
typeSig!string().assertEqual("s");
|
||||||
|
typeSig!(Variant!int)().assertEqual("v");
|
||||||
// structs
|
// structs
|
||||||
typeSig!(Tuple!(int,string,string)).assertEqual("(iss)");
|
typeSig!(Tuple!(int,string,string)).assertEqual("(iss)");
|
||||||
typeSig!(Tuple!(int,string,Tuple!(int,"k",double,"x"))).assertEqual("(is(id))");
|
typeSig!(Tuple!(int,string,Variant!int,Tuple!(int,"k",double,"x"))).assertEqual("(isv(id))");
|
||||||
// arrays
|
// arrays
|
||||||
typeSig!(int[]).assertEqual("ai");
|
typeSig!(int[]).assertEqual("ai");
|
||||||
|
typeSig!(Variant!int[]).assertEqual("av");
|
||||||
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
typeSig!(Tuple!(byte)[][]).assertEqual("aa(y)");
|
||||||
// multiple arguments
|
// multiple arguments
|
||||||
typeSigAll!(int,bool).assertEqual("ib");
|
typeSigAll!(int,bool).assertEqual("ib");
|
||||||
|
|
Loading…
Reference in a new issue