fix immutable/const types & add type convenience
Before it was not properly possible to use static immutable name = interfaceName(...) in a message, which is now fixed
This commit is contained in:
parent
f988709b7a
commit
2fde2e12af
|
@ -17,7 +17,7 @@ import std.variant : VariantN;
|
||||||
void buildIter(TS...)(DBusMessageIter* iter, TS args)
|
void buildIter(TS...)(DBusMessageIter* iter, TS args)
|
||||||
if (allCanDBus!TS) {
|
if (allCanDBus!TS) {
|
||||||
foreach (index, arg; args) {
|
foreach (index, arg; args) {
|
||||||
alias TS[index] T;
|
alias T = Unqual!(TS[index]);
|
||||||
static if (is(T == string) || is(T == InterfaceName) || is(T == BusName)) {
|
static if (is(T == string) || is(T == InterfaceName) || is(T == BusName)) {
|
||||||
immutable(char)* cStr = arg.toStringz();
|
immutable(char)* cStr = arg.toStringz();
|
||||||
dbus_message_iter_append_basic(iter, typeCode!T, &cStr);
|
dbus_message_iter_append_basic(iter, typeCode!T, &cStr);
|
||||||
|
@ -172,10 +172,10 @@ void buildIter(TS...)(DBusMessageIter* iter, TS args)
|
||||||
}
|
}
|
||||||
|
|
||||||
T readIter(T)(DBusMessageIter* iter)
|
T readIter(T)(DBusMessageIter* iter)
|
||||||
if (is(T == enum) && !is(T == InterfaceName) && !is(T == BusName)) {
|
if (is(T == enum) && !is(Unqual!T == InterfaceName) && !is(Unqual!T == BusName)) {
|
||||||
import std.algorithm.searching : canFind;
|
import std.algorithm.searching : canFind;
|
||||||
|
|
||||||
alias OriginalType!T B;
|
alias B = Unqual!(OriginalType!T);
|
||||||
|
|
||||||
B value = readIter!B(iter);
|
B value = readIter!B(iter);
|
||||||
enforce(only(EnumMembers!T).canFind(value), new InvalidValueException(value, T.stringof));
|
enforce(only(EnumMembers!T).canFind(value), new InvalidValueException(value, T.stringof));
|
||||||
|
@ -197,8 +197,10 @@ T readIter(T)(DBusMessageIter* iter)
|
||||||
return T(cast(E) value);
|
return T(cast(E) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
T readIter(T)(DBusMessageIter* iter)
|
U readIter(U)(DBusMessageIter* iter)
|
||||||
if (!(is(T == enum) && !is(T == InterfaceName) && !is(T == BusName)) && !isInstanceOf!(BitFlags, T) && canDBus!T) {
|
if (!(is(U == enum) && !is(Unqual!U == InterfaceName) && !is(Unqual!U == BusName)) && !isInstanceOf!(BitFlags, U) && canDBus!U) {
|
||||||
|
alias T = Unqual!U;
|
||||||
|
|
||||||
auto argType = dbus_message_iter_get_arg_type(iter);
|
auto argType = dbus_message_iter_get_arg_type(iter);
|
||||||
T ret;
|
T ret;
|
||||||
|
|
||||||
|
@ -214,7 +216,7 @@ T readIter(T)(DBusMessageIter* iter)
|
||||||
ret.explicitVariant = true;
|
ret.explicitVariant = true;
|
||||||
}
|
}
|
||||||
dbus_message_iter_next(iter);
|
dbus_message_iter_next(iter);
|
||||||
return ret;
|
return cast(U) ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +228,7 @@ T readIter(T)(DBusMessageIter* iter)
|
||||||
const(char)* cStr;
|
const(char)* cStr;
|
||||||
dbus_message_iter_get_basic(iter, &cStr);
|
dbus_message_iter_get_basic(iter, &cStr);
|
||||||
string str = cStr.fromStringz().idup; // copy string
|
string str = cStr.fromStringz().idup; // copy string
|
||||||
static if (is(T == string) || is(T == InterfaceName) || is(T == BusName)) {
|
static if (is(T == string) || is(T : InterfaceName) || is(T : BusName)) {
|
||||||
ret = cast(T)str;
|
ret = cast(T)str;
|
||||||
} else {
|
} else {
|
||||||
ret = ObjectPath(str);
|
ret = ObjectPath(str);
|
||||||
|
@ -239,20 +241,20 @@ T readIter(T)(DBusMessageIter* iter)
|
||||||
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 t : U[], U)) {
|
} else static if (is(T t : S[], S)) {
|
||||||
assert(dbus_message_iter_get_element_type(iter) == typeCode!U);
|
assert(dbus_message_iter_get_element_type(iter) == typeCode!S);
|
||||||
|
|
||||||
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)) {
|
static if (is(S == DictionaryEntry!(K, V), K, V)) {
|
||||||
DBusMessageIter entry;
|
DBusMessageIter entry;
|
||||||
dbus_message_iter_recurse(&sub, &entry);
|
dbus_message_iter_recurse(&sub, &entry);
|
||||||
ret ~= U(readIter!K(&entry), readIter!V(&entry));
|
ret ~= S(readIter!K(&entry), readIter!V(&entry));
|
||||||
dbus_message_iter_next(&sub);
|
dbus_message_iter_next(&sub);
|
||||||
} else {
|
} else {
|
||||||
ret ~= readIter!U(&sub);
|
ret ~= readIter!S(&sub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else static if (isInstanceOf!(Variant, T)) {
|
} else static if (isInstanceOf!(Variant, T)) {
|
||||||
|
@ -295,13 +297,13 @@ T readIter(T)(DBusMessageIter* iter)
|
||||||
|
|
||||||
if (ret.type == 's') {
|
if (ret.type == 's') {
|
||||||
ret.str = readIter!string(iter);
|
ret.str = readIter!string(iter);
|
||||||
return ret;
|
return cast(U) ret;
|
||||||
} else if (ret.type == 'o') {
|
} else if (ret.type == 'o') {
|
||||||
ret.obj = readIter!ObjectPath(iter);
|
ret.obj = readIter!ObjectPath(iter);
|
||||||
return ret;
|
return cast(U) ret;
|
||||||
} else if (ret.type == 'b') {
|
} else if (ret.type == 'b') {
|
||||||
ret.boolean = readIter!bool(iter);
|
ret.boolean = readIter!bool(iter);
|
||||||
return ret;
|
return cast(U) ret;
|
||||||
} else if (dbus_type_is_basic(ret.type)) {
|
} else if (dbus_type_is_basic(ret.type)) {
|
||||||
dbus_message_iter_get_basic(iter, &ret.int64);
|
dbus_message_iter_get_basic(iter, &ret.int64);
|
||||||
} else if (ret.type == 'a') {
|
} else if (ret.type == 'a') {
|
||||||
|
@ -351,7 +353,7 @@ T readIter(T)(DBusMessageIter* iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
dbus_message_iter_next(iter);
|
dbus_message_iter_next(iter);
|
||||||
return ret;
|
return cast(U) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readIterTuple(Tup)(DBusMessageIter* iter, ref Tup tuple)
|
void readIterTuple(Tup)(DBusMessageIter* iter, ref Tup tuple)
|
||||||
|
|
|
@ -46,6 +46,10 @@ struct ObjectPath {
|
||||||
return hashOf(_value);
|
return hashOf(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T opCast(T : ObjectPath)() const pure @nogc nothrow @safe {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
T opCast(T : string)() const pure @nogc nothrow @safe {
|
T opCast(T : string)() const pure @nogc nothrow @safe {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -482,25 +486,26 @@ struct DBusAny {
|
||||||
TypeMismatchException if the DBus type of the current value of the
|
TypeMismatchException if the DBus type of the current value of the
|
||||||
DBusAny object is not the same as the DBus type used to represent T.
|
DBusAny object is not the same as the DBus type used to represent T.
|
||||||
+/
|
+/
|
||||||
T get(T)() @property const
|
U get(U)() @property const
|
||||||
if (staticIndexOf!(T, BasicTypes) >= 0) {
|
if (staticIndexOf!(Unqual!U, BasicTypes) >= 0) {
|
||||||
|
alias T = Unqual!U;
|
||||||
enforce(type == typeCode!T, new TypeMismatchException(
|
enforce(type == typeCode!T, new TypeMismatchException(
|
||||||
"Cannot get a " ~ T.stringof ~ " from a DBusAny with" ~ " a value of DBus type '" ~ typeSig ~ "'.",
|
"Cannot get a " ~ T.stringof ~ " from a DBusAny with" ~ " a value of DBus type '" ~ typeSig ~ "'.",
|
||||||
typeCode!T, type));
|
typeCode!T, type));
|
||||||
|
|
||||||
static if (isIntegral!T) {
|
static if (isIntegral!T) {
|
||||||
enum memberName = (isUnsigned!T ? "uint" : "int") ~ (T.sizeof * 8).to!string;
|
enum memberName = (isUnsigned!T ? "uint" : "int") ~ (T.sizeof * 8).to!string;
|
||||||
return __traits(getMember, this, memberName);
|
return cast(U) __traits(getMember, this, memberName);
|
||||||
} else static if (is(T == double)) {
|
} else static if (is(T == double)) {
|
||||||
return float64;
|
return cast(U) float64;
|
||||||
} else static if (is(T == string)) {
|
} else static if (is(T == string)) {
|
||||||
return str;
|
return cast(U) str;
|
||||||
} else static if (is(T == InterfaceName) || is(T == BusName)) {
|
} else static if (is(T == InterfaceName) || is(T == BusName)) {
|
||||||
return cast(T) str;
|
return cast(U) str;
|
||||||
} else static if (is(T == ObjectPath)) {
|
} else static if (is(T == ObjectPath)) {
|
||||||
return obj;
|
return cast(U) obj;
|
||||||
} else static if (is(T == bool)) {
|
} else static if (is(T == bool)) {
|
||||||
return boolean;
|
return cast(U) boolean;
|
||||||
} else {
|
} else {
|
||||||
static assert(false);
|
static assert(false);
|
||||||
}
|
}
|
||||||
|
@ -696,6 +701,21 @@ struct DBusAny {
|
||||||
return uint64 == b.uint64;
|
return uint64 == b.uint64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns: true if this variant is an integer.
|
||||||
|
bool typeIsIntegral() const @property {
|
||||||
|
return type.dbusIsIntegral;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns: true if this variant is a floating point value.
|
||||||
|
bool typeIsFloating() const @property {
|
||||||
|
return type.dbusIsFloating;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns: true if this variant is an integer or a floating point value.
|
||||||
|
bool typeIsNumeric() const @property {
|
||||||
|
return type.dbusIsNumeric;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest {
|
unittest {
|
||||||
|
@ -706,23 +726,26 @@ unittest {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test(T)(T value, DBusAny b) {
|
void test(bool testGet = false, T)(T value, DBusAny b) {
|
||||||
assertEqual(DBusAny(value), b);
|
assertEqual(DBusAny(value), b);
|
||||||
assertEqual(b.to!T, value);
|
assertEqual(b.to!T, value);
|
||||||
|
static if (testGet)
|
||||||
|
assertEqual(b.get!T, value);
|
||||||
b.toString();
|
b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
test(cast(ubyte) 184, set!"uint8"(DBusAny('y', null, false), cast(ubyte) 184));
|
test!true(cast(ubyte) 184, set!"uint8"(DBusAny('y', null, false), cast(ubyte) 184));
|
||||||
test(cast(short) 184, set!"int16"(DBusAny('n', null, false), cast(short) 184));
|
test(cast(byte) 184, set!"uint8"(DBusAny('y', null, false), cast(byte) 184));
|
||||||
test(cast(ushort) 184, set!"uint16"(DBusAny('q', null, false), cast(ushort) 184));
|
test!true(cast(short) 184, set!"int16"(DBusAny('n', null, false), cast(short) 184));
|
||||||
test(cast(int) 184, set!"int32"(DBusAny('i', null, false), cast(int) 184));
|
test!true(cast(ushort) 184, set!"uint16"(DBusAny('q', null, false), cast(ushort) 184));
|
||||||
test(cast(uint) 184, set!"uint32"(DBusAny('u', null, false), cast(uint) 184));
|
test!true(cast(int) 184, set!"int32"(DBusAny('i', null, false), cast(int) 184));
|
||||||
test(cast(long) 184, set!"int64"(DBusAny('x', null, false), cast(long) 184));
|
test!true(cast(uint) 184, set!"uint32"(DBusAny('u', null, false), cast(uint) 184));
|
||||||
test(cast(ulong) 184, set!"uint64"(DBusAny('t', null, false), cast(ulong) 184));
|
test!true(cast(long) 184, set!"int64"(DBusAny('x', null, false), cast(long) 184));
|
||||||
test(1.84, set!"float64"(DBusAny('d', null, false), 1.84));
|
test!true(cast(ulong) 184, set!"uint64"(DBusAny('t', null, false), cast(ulong) 184));
|
||||||
test(true, set!"boolean"(DBusAny('b', null, false), true));
|
test!true(1.84, set!"float64"(DBusAny('d', null, false), 1.84));
|
||||||
test("abc", set!"str"(DBusAny('s', null, false), "abc"));
|
test!true(true, set!"boolean"(DBusAny('b', null, false), true));
|
||||||
test(ObjectPath("/foo/Bar"), set!"obj"(DBusAny('o', null, false), ObjectPath("/foo/Bar")));
|
test!true("abc", set!"str"(DBusAny('s', null, false), "abc"));
|
||||||
|
test!true(ObjectPath("/foo/Bar"), set!"obj"(DBusAny('o', null, false), ObjectPath("/foo/Bar")));
|
||||||
test(cast(ubyte[])[1, 2, 3], set!"binaryData"(DBusAny('a', ['y'], false),
|
test(cast(ubyte[])[1, 2, 3], set!"binaryData"(DBusAny('a', ['y'], false),
|
||||||
cast(ubyte[])[1, 2, 3]));
|
cast(ubyte[])[1, 2, 3]));
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,8 @@ package // Don't add to the API yet, 'cause I intend to move it later
|
||||||
alias BasicTypes = AliasSeq!(bool, ubyte, short, ushort, int, uint, long, ulong,
|
alias BasicTypes = AliasSeq!(bool, ubyte, short, ushort, int, uint, long, ulong,
|
||||||
double, string, ObjectPath, InterfaceName, BusName);
|
double, string, ObjectPath, InterfaceName, BusName);
|
||||||
|
|
||||||
template basicDBus(T) {
|
template basicDBus(U) {
|
||||||
|
alias T = Unqual!U;
|
||||||
static if (staticIndexOf!(T, BasicTypes) >= 0) {
|
static if (staticIndexOf!(T, BasicTypes) >= 0) {
|
||||||
enum basicDBus = true;
|
enum basicDBus = true;
|
||||||
} else static if (is(T B == enum)) {
|
} else static if (is(T B == enum)) {
|
||||||
|
@ -70,7 +71,8 @@ template basicDBus(T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template canDBus(T) {
|
template canDBus(U) {
|
||||||
|
alias T = Unqual!U;
|
||||||
static if (basicDBus!T || is(T == DBusAny)) {
|
static if (basicDBus!T || is(T == DBusAny)) {
|
||||||
enum canDBus = true;
|
enum canDBus = true;
|
||||||
} else static if (isInstanceOf!(Variant, T)) {
|
} else static if (isInstanceOf!(Variant, T)) {
|
||||||
|
@ -106,8 +108,9 @@ unittest {
|
||||||
(canDBus!(int[string])).assertTrue();
|
(canDBus!(int[string])).assertTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
string typeSig(T)()
|
string typeSig(U)()
|
||||||
if (canDBus!T) {
|
if (canDBus!U) {
|
||||||
|
alias T = Unqual!U;
|
||||||
static if (is(T == ubyte)) {
|
static if (is(T == ubyte)) {
|
||||||
return "y";
|
return "y";
|
||||||
} else static if (is(T == bool)) {
|
} else static if (is(T == bool)) {
|
||||||
|
@ -205,6 +208,33 @@ int typeCode(T)()
|
||||||
return 'e';
|
return 'e';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Params:
|
||||||
|
type = the type code of a type (first character in a type string)
|
||||||
|
Returns: true if the given type is an integer.
|
||||||
|
*/
|
||||||
|
bool dbusIsIntegral(int type) @property {
|
||||||
|
return type == 'y' || type == 'n' || type == 'q' || type == 'i' || type == 'u' || type == 'x' || type == 't';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Params:
|
||||||
|
type = the type code of a type (first character in a type string)
|
||||||
|
Returns: true if the given type is a floating point value.
|
||||||
|
*/
|
||||||
|
bool dbusIsFloating(int type) @property {
|
||||||
|
return type == 'd';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Params:
|
||||||
|
type = the type code of a type (first character in a type string)
|
||||||
|
Returns: true if the given type is an integer or a floating point value.
|
||||||
|
*/
|
||||||
|
bool dbusIsNumeric(int type) @property {
|
||||||
|
return dbusIsIntegral(type) || dbusIsFloating(type);
|
||||||
|
}
|
||||||
|
|
||||||
unittest {
|
unittest {
|
||||||
import dunit.toolkit;
|
import dunit.toolkit;
|
||||||
|
|
||||||
|
@ -216,6 +246,10 @@ 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!InterfaceName().assertEqual("s");
|
||||||
|
typeSig!(immutable(InterfaceName))().assertEqual("s");
|
||||||
|
typeSig!ObjectPath().assertEqual("o");
|
||||||
|
typeSig!(immutable(ObjectPath))().assertEqual("o");
|
||||||
typeSig!(Variant!int)().assertEqual("v");
|
typeSig!(Variant!int)().assertEqual("v");
|
||||||
// enums
|
// enums
|
||||||
enum E : ubyte {
|
enum E : ubyte {
|
||||||
|
|
Loading…
Reference in a new issue