diff --git a/source/ddbus/conv.d b/source/ddbus/conv.d index 85c5369..3b49e0e 100644 --- a/source/ddbus/conv.d +++ b/source/ddbus/conv.d @@ -132,7 +132,24 @@ T readIter(T)(DBusMessageIter *iter) if (is(T == enum)) { return cast(T) value; } -T readIter(T)(DBusMessageIter *iter) if (!is(T == enum) && canDBus!T) { +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; static if(!isVariant!T || is(T == Variant!DBusAny)) { @@ -331,6 +348,10 @@ unittest { 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(); } diff --git a/source/ddbus/util.d b/source/ddbus/util.d index 320a55c..968e89a 100644 --- a/source/ddbus/util.d +++ b/source/ddbus/util.d @@ -49,6 +49,9 @@ template basicDBus(T) { 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 { enum basicDBus = false; } @@ -111,6 +114,9 @@ string typeSig(T)() if(canDBus!T) { 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)) { static assert(false, "Cannot determine type signature of DBusAny. Change to Variant!DBusAny if a variant was desired."); } else static if(isTuple!T) { @@ -179,6 +185,9 @@ unittest { 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 typeSig!(Tuple!(int,string,string)).assertEqual("(iss)"); typeSig!(Tuple!(int,string,Variant!int,Tuple!(int,"k",double,"x"))).assertEqual("(isv(id))");