Added FileDescriptor support
Some DBus methods return file descriptors, such as "org.freedesktop.login1.Manager.Inhibit". This commit adds support for these. I followed the same enum type defining pattern I've seen in the code, such as with InterfaceNames and BusNames, to prevent integers and fileDescriptors implicitly casting to each other. Note that it is kinda hard to test with reading and writing fileDescriptors, as DBus will duplicate the file descriptor when reading, leading to relatively unpredicatable behaviour. I also must admit I focussed most of my attention to reading file descriptors and less to writing file descriptors, as I don't know a good way to test those.
This commit is contained in:
parent
ab994acdb3
commit
3b1cc9b453
|
@ -172,7 +172,7 @@ void buildIter(TS...)(DBusMessageIter* iter, TS args)
|
|||
}
|
||||
|
||||
T readIter(T)(DBusMessageIter* iter)
|
||||
if (is(T == enum) && !is(T == InterfaceName) && !is(T == BusName)) {
|
||||
if (is(T == enum) && !is(T == InterfaceName) && !is(T == BusName) && !is(T == FileDescriptor)) {
|
||||
import std.algorithm.searching : canFind;
|
||||
|
||||
alias OriginalType!T B;
|
||||
|
@ -198,7 +198,8 @@ T readIter(T)(DBusMessageIter* iter)
|
|||
}
|
||||
|
||||
T readIter(T)(DBusMessageIter* iter)
|
||||
if (!(is(T == enum) && !is(T == InterfaceName) && !is(T == BusName)) && !isInstanceOf!(BitFlags, T) && canDBus!T) {
|
||||
if (!(is(T == enum) && !is(T == InterfaceName) && !is(T == BusName) && !is(T == FileDescriptor))
|
||||
&& !isInstanceOf!(BitFlags, T) && canDBus!T) {
|
||||
auto argType = dbus_message_iter_get_arg_type(iter);
|
||||
T ret;
|
||||
|
||||
|
|
|
@ -171,6 +171,17 @@ InterfaceName interfaceName(string path) pure @nogc nothrow @safe {
|
|||
return cast(InterfaceName) path;
|
||||
}
|
||||
|
||||
/// Serving as a typesafe alias for a FileDescriptor.
|
||||
enum FileDescriptor : int {
|
||||
none = -1,
|
||||
max = int.max
|
||||
}
|
||||
|
||||
/// Casts an integer to a FileDescriptor.
|
||||
FileDescriptor fileDescriptor(int fileNo) pure @nogc nothrow @safe {
|
||||
return cast(FileDescriptor) fileNo;
|
||||
}
|
||||
|
||||
unittest {
|
||||
import dunit.toolkit;
|
||||
|
||||
|
@ -284,6 +295,9 @@ struct DBusAny {
|
|||
} else static if (is(T == int)) {
|
||||
this(typeCode!int, null, false);
|
||||
int32 = cast(int) value;
|
||||
} else static if (is(T == FileDescriptor)) {
|
||||
this(typeCode!FileDescriptor, null, false);
|
||||
int32 = cast(int) value;
|
||||
} else static if (is(T == uint)) {
|
||||
this(typeCode!uint, null, false);
|
||||
uint32 = cast(uint) value;
|
||||
|
@ -459,6 +473,9 @@ struct DBusAny {
|
|||
case 'e':
|
||||
valueStr = entry.key.toString ~ ": " ~ entry.value.toString;
|
||||
break;
|
||||
case 'h':
|
||||
valueStr = int32.to!string;
|
||||
break;
|
||||
default:
|
||||
valueStr = "unknown";
|
||||
break;
|
||||
|
@ -488,7 +505,9 @@ struct DBusAny {
|
|||
"Cannot get a " ~ T.stringof ~ " from a DBusAny with" ~ " a value of DBus type '" ~ typeSig ~ "'.",
|
||||
typeCode!T, type));
|
||||
|
||||
static if (isIntegral!T) {
|
||||
static if (is(T == FileDescriptor)) {
|
||||
return fileDescriptor(int32);
|
||||
} else static if (isIntegral!T) {
|
||||
enum memberName = (isUnsigned!T ? "uint" : "int") ~ (T.sizeof * 8).to!string;
|
||||
return __traits(getMember, this, memberName);
|
||||
} else static if (is(T == double)) {
|
||||
|
@ -730,6 +749,7 @@ unittest {
|
|||
test(variant(cast(short) 184), set!"int16"(DBusAny('n', null, true), cast(short) 184));
|
||||
test(variant(cast(ushort) 184), set!"uint16"(DBusAny('q', null, true), cast(ushort) 184));
|
||||
test(variant(cast(int) 184), set!"int32"(DBusAny('i', null, true), cast(int) 184));
|
||||
test(variant(cast(FileDescriptor) 184), set!"int32"(DBusAny('h', null, true), cast(FileDescriptor) 184));
|
||||
test(variant(cast(uint) 184), set!"uint32"(DBusAny('u', null, true), cast(uint) 184));
|
||||
test(variant(cast(long) 184), set!"int64"(DBusAny('x', null, true), cast(long) 184));
|
||||
test(variant(cast(ulong) 184), set!"uint64"(DBusAny('t', null, true), cast(ulong) 184));
|
||||
|
|
|
@ -55,7 +55,7 @@ template allCanDBus(TS...) {
|
|||
+/
|
||||
package // Don't add to the API yet, 'cause I intend to move it later
|
||||
alias BasicTypes = AliasSeq!(bool, byte, short, ushort, int, uint, long, ulong,
|
||||
double, string, ObjectPath, InterfaceName, BusName);
|
||||
double, string, ObjectPath, InterfaceName, BusName, FileDescriptor);
|
||||
|
||||
template basicDBus(T) {
|
||||
static if (staticIndexOf!(T, BasicTypes) >= 0) {
|
||||
|
@ -104,6 +104,7 @@ unittest {
|
|||
(canDBus!(Tuple!(int[], bool, Variant!short))).assertTrue();
|
||||
(canDBus!(Tuple!(int[], int[string]))).assertTrue();
|
||||
(canDBus!(int[string])).assertTrue();
|
||||
(canDBus!FileDescriptor).assertTrue();
|
||||
}
|
||||
|
||||
string typeSig(T)()
|
||||
|
@ -116,6 +117,8 @@ string typeSig(T)()
|
|||
return "n";
|
||||
} else static if (is(T == ushort)) {
|
||||
return "q";
|
||||
} else static if (is(T == FileDescriptor)) {
|
||||
return "h";
|
||||
} else static if (is(T == int)) {
|
||||
return "i";
|
||||
} else static if (is(T == uint)) {
|
||||
|
@ -217,6 +220,7 @@ unittest {
|
|||
typeSig!bool().assertEqual("b");
|
||||
typeSig!string().assertEqual("s");
|
||||
typeSig!(Variant!int)().assertEqual("v");
|
||||
typeSig!FileDescriptor().assertEqual("h");
|
||||
// enums
|
||||
enum E : byte {
|
||||
a,
|
||||
|
@ -256,9 +260,10 @@ unittest {
|
|||
string d;
|
||||
S1 e;
|
||||
uint f;
|
||||
FileDescriptor g;
|
||||
}
|
||||
|
||||
typeSig!S2.assertEqual("(vs(ids)u)");
|
||||
typeSig!S2.assertEqual("(vs(ids)uh)");
|
||||
// arrays
|
||||
typeSig!(int[]).assertEqual("ai");
|
||||
typeSig!(Variant!int[]).assertEqual("av");
|
||||
|
|
Loading…
Reference in a new issue