commit
15ae9fec23
|
@ -1,7 +1,7 @@
|
||||||
module ddbus.conv;
|
module ddbus.conv;
|
||||||
|
|
||||||
import ddbus.c_lib;
|
import ddbus.c_lib;
|
||||||
import ddbus.exception : TypeMismatchException;
|
import ddbus.exception : InvalidValueException, TypeMismatchException;
|
||||||
import ddbus.util;
|
import ddbus.util;
|
||||||
import ddbus.thin;
|
import ddbus.thin;
|
||||||
import std.exception : enforce;
|
import std.exception : enforce;
|
||||||
|
@ -119,8 +119,39 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
T readIter(T)(DBusMessageIter *iter) if (is(T == enum)) {
|
||||||
|
import std.algorithm.searching : canFind;
|
||||||
|
|
||||||
|
alias OriginalType!T B;
|
||||||
|
|
||||||
|
B value = readIter!B(iter);
|
||||||
|
enforce(
|
||||||
|
only(EnumMembers!T).canFind(value),
|
||||||
|
new InvalidValueException(value, T.stringof)
|
||||||
|
);
|
||||||
|
return cast(T) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
T readIter(T)(DBusMessageIter *iter) if (isInstanceOf!(BitFlags, T)) {
|
||||||
|
import std.algorithm.iteration : fold;
|
||||||
|
|
||||||
|
alias TemplateArgsOf!T[0] E;
|
||||||
|
alias OriginalType!E B;
|
||||||
|
|
||||||
|
B mask = only(EnumMembers!E).fold!((a, b) => a | b);
|
||||||
|
|
||||||
|
B value = readIter!B(iter);
|
||||||
|
enforce(
|
||||||
|
!(value & ~mask),
|
||||||
|
new InvalidValueException(value, T.stringof)
|
||||||
|
);
|
||||||
|
|
||||||
|
return T(cast(E) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
T readIter(T)(DBusMessageIter *iter) if (!is(T == enum) && !isInstanceOf!(BitFlags, T) && canDBus!T) {
|
||||||
T ret;
|
T ret;
|
||||||
|
|
||||||
static if(!isVariant!T || is(T == Variant!DBusAny)) {
|
static if(!isVariant!T || is(T == Variant!DBusAny)) {
|
||||||
if(dbus_message_iter_get_arg_type(iter) == 'v') {
|
if(dbus_message_iter_get_arg_type(iter) == 'v') {
|
||||||
DBusMessageIter sub;
|
DBusMessageIter sub;
|
||||||
|
@ -237,6 +268,7 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
} else static if(basicDBus!T) {
|
} else static if(basicDBus!T) {
|
||||||
dbus_message_iter_get_basic(iter, &ret);
|
dbus_message_iter_get_basic(iter, &ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbus_message_iter_next(iter);
|
dbus_message_iter_next(iter);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +301,7 @@ unittest {
|
||||||
complexVar.data.type.assertEqual('a');
|
complexVar.data.type.assertEqual('a');
|
||||||
complexVar.data.signature.assertEqual("{sv}".dup);
|
complexVar.data.signature.assertEqual("{sv}".dup);
|
||||||
tupleMember.signature.assertEqual("(vviai(vi)a{ss})");
|
tupleMember.signature.assertEqual("(vviai(vi)a{ss})");
|
||||||
|
|
||||||
auto args = tuple(5,true,"wow",var(5.9),[6,5],tuple(6.2,4,[["lol"]],emptyB,var([4,2])),map,anyVar,complexVar);
|
auto args = tuple(5,true,"wow",var(5.9),[6,5],tuple(6.2,4,[["lol"]],emptyB,var([4,2])),map,anyVar,complexVar);
|
||||||
msg.build(args.expand);
|
msg.build(args.expand);
|
||||||
msg.signature().assertEqual("ibsvai(diaasabv)a{ss}tv");
|
msg.signature().assertEqual("ibsvai(diaasabv)a{ss}tv");
|
||||||
|
@ -298,3 +331,27 @@ unittest {
|
||||||
readIter!DBusAny(&iter).assertEqual(anyVar);
|
readIter!DBusAny(&iter).assertEqual(anyVar);
|
||||||
readIter!(Variant!DBusAny)(&iter).assertEqual(complexVar);
|
readIter!(Variant!DBusAny)(&iter).assertEqual(complexVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
import dunit.toolkit;
|
||||||
|
import ddbus.thin;
|
||||||
|
|
||||||
|
enum E : int { a, b, c }
|
||||||
|
enum F : uint { x = 1, y = 2, z = 4 }
|
||||||
|
|
||||||
|
Message msg = Message("org.example.wow", "/wut", "org.test.iface", "meth2");
|
||||||
|
msg.build(E.c, 4, 5u, 8u);
|
||||||
|
|
||||||
|
DBusMessageIter iter, iter2;
|
||||||
|
dbus_message_iter_init(msg.msg, &iter);
|
||||||
|
|
||||||
|
readIter!E(&iter).assertEqual(E.c);
|
||||||
|
readIter!E(&iter).assertThrow!InvalidValueException();
|
||||||
|
|
||||||
|
iter2 = iter;
|
||||||
|
readIter!F(&iter).assertThrow!InvalidValueException();
|
||||||
|
readIter!(BitFlags!F)(&iter2).assertEqual(BitFlags!F(F.x, F.z));
|
||||||
|
|
||||||
|
readIter!F(&iter).assertThrow!InvalidValueException();
|
||||||
|
readIter!(BitFlags!F)(&iter2).assertThrow!InvalidValueException();
|
||||||
|
}
|
||||||
|
|
|
@ -64,3 +64,29 @@ class TypeMismatchException : Exception {
|
||||||
int _expectedType;
|
int _expectedType;
|
||||||
int _actualType;
|
int _actualType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Thrown during type conversion between DBus types and D types when a value is
|
||||||
|
encountered that can not be represented in the target type.
|
||||||
|
|
||||||
|
This exception should not normally be thrown except when dealing with D types
|
||||||
|
that have a constrained value set, such as Enums.
|
||||||
|
+/
|
||||||
|
class InvalidValueException : Exception {
|
||||||
|
package this(Source)(
|
||||||
|
Source value,
|
||||||
|
string targetType,
|
||||||
|
string file = __FILE__,
|
||||||
|
size_t line = __LINE__,
|
||||||
|
Throwable next = null
|
||||||
|
) {
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
|
static if(__traits(compiles, value.to!string))
|
||||||
|
string valueString = value.to!string;
|
||||||
|
else
|
||||||
|
string valueString = "(unprintable)";
|
||||||
|
|
||||||
|
super("Value " ~ valueString ~ " cannot be represented in type " ~ targetType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,11 @@ template basicDBus(T) {
|
||||||
|| is (T == double) || is (T == string) || is(T == bool)
|
|| is (T == double) || is (T == string) || is(T == bool)
|
||||||
|| is (T == ObjectPath)) {
|
|| is (T == ObjectPath)) {
|
||||||
enum basicDBus = true;
|
enum basicDBus = true;
|
||||||
|
} else static if(is(T B == enum)) {
|
||||||
|
enum basicDBus = basicDBus!B;
|
||||||
|
} else static if(isInstanceOf!(BitFlags, T)) {
|
||||||
|
alias TemplateArgsOf!T[0] E;
|
||||||
|
enum basicDBus = basicDBus!E;
|
||||||
} else {
|
} else {
|
||||||
enum basicDBus = false;
|
enum basicDBus = false;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +76,7 @@ template canDBus(T) {
|
||||||
enum canDBus = false;
|
enum canDBus = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest {
|
unittest {
|
||||||
import dunit.toolkit;
|
import dunit.toolkit;
|
||||||
(canDBus!int).assertTrue();
|
(canDBus!int).assertTrue();
|
||||||
|
@ -106,6 +112,11 @@ string typeSig(T)() if(canDBus!T) {
|
||||||
return "o";
|
return "o";
|
||||||
} else static if(isVariant!T) {
|
} else static if(isVariant!T) {
|
||||||
return "v";
|
return "v";
|
||||||
|
} else static if(is(T B == enum)) {
|
||||||
|
return typeSig!B;
|
||||||
|
} else static if(isInstanceOf!(BitFlags, T)) {
|
||||||
|
alias TemplateArgsOf!T[0] E;
|
||||||
|
return typeSig!E;
|
||||||
} else static if(is(T == DBusAny)) {
|
} else static if(is(T == DBusAny)) {
|
||||||
static assert(false, "Cannot determine type signature of DBusAny. Change to Variant!DBusAny if a variant was desired.");
|
static assert(false, "Cannot determine type signature of DBusAny. Change to Variant!DBusAny if a variant was desired.");
|
||||||
} else static if(isTuple!T) {
|
} else static if(isTuple!T) {
|
||||||
|
@ -169,6 +180,14 @@ unittest {
|
||||||
typeSig!bool().assertEqual("b");
|
typeSig!bool().assertEqual("b");
|
||||||
typeSig!string().assertEqual("s");
|
typeSig!string().assertEqual("s");
|
||||||
typeSig!(Variant!int)().assertEqual("v");
|
typeSig!(Variant!int)().assertEqual("v");
|
||||||
|
// enums
|
||||||
|
enum E : byte { a, b, c }
|
||||||
|
typeSig!E().assertEqual(typeSig!byte());
|
||||||
|
enum U : string { One = "One", Two = "Two" }
|
||||||
|
typeSig!U().assertEqual(typeSig!string());
|
||||||
|
// bit flags
|
||||||
|
enum F : uint { a = 1, b = 2, c = 4 }
|
||||||
|
typeSig!(BitFlags!F)().assertEqual(typeSig!uint());
|
||||||
// structs
|
// structs
|
||||||
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))");
|
||||||
|
|
Loading…
Reference in a new issue