diff --git a/source/ddbus/attributes.d b/source/ddbus/attributes.d new file mode 100644 index 0000000..1658be5 --- /dev/null +++ b/source/ddbus/attributes.d @@ -0,0 +1,65 @@ +module ddbus.attributes; + +import std.meta : allSatisfy; +import std.traits : getUDAs; +import std.typecons : BitFlags, Flag; + +/++ + Flags for use with dbusMarshaling UDA + + Default is to include public fields only ++/ +enum MarshalingFlag : ubyte { + includePrivateFields = 1 << 0, /// Automatically include private fields + manualOnly = 1 << 7 /// Only include fields with explicit + /// `@Yes.DBusMarshal`. This overrides any + /// `include` flags. +} + +/++ + UDA for specifying DBus marshaling options on structs ++/ +auto dbusMarshaling(Args)(Args args ...) + if (allSatisfy!(isMarshalingFlag, Args)) { + return BitFlags!MarshalingFlag(args); +} + +package(ddbus) template isAllowedField(alias field) { + private enum flags = marshalingFlags!(__traits(parent, field)); + private alias getUDAs!(field, Flag!"DBusMarshal") UDAs; + + static if (UDAs.length != 0) { + static assert (UDAs.length == 1, + "Only one UDA of type Flag!\"DBusMarshal\" allowed on struct field."); + static assert (is(typeof(UDAs[0]) == Flag!"DBusMarshal"), + "Did you intend to add UDA Yes.DBusMarshal or No.DBusMarshal?"); + enum isAllowedField = cast(bool) UDAs[0]; + } else static if (!(flags & MarshalingFlag.manualOnly)) { + static if (__traits(getProtection, field) == "public") + enum isAllowedField = true; + else static if (cast(bool) (flags & MarshalingFlag.includePrivateFields)) + enum isAllowedField = true; + else + enum isAllowedField = false; + } else + enum isAllowedField = false; +} + +private template isMarshalingFlag(T) { + enum isMarshalingFlag = is(T == MarshalingFlag); +} + +private template marshalingFlags(S) if (is(S == struct)) { + private alias getUDAs!(S, BitFlags!MarshalingFlag) UDAs; + + static if (UDAs.length == 0) + enum marshalingFlags = BitFlags!MarshalingFlag.init; + else { + static assert (UDAs.length == 1, + "Only one @dbusMarshaling UDA allowed on type."); + static assert (is(typeof(UDAs[0]) == BitFlags!MarshalingFlag), + "Huh? Did you intend to use @dbusMarshaling UDA?"); + enum marshalingFlags = UDAs[0]; + } +} + diff --git a/source/ddbus/conv.d b/source/ddbus/conv.d index 1a85bdd..d3a0f6e 100644 --- a/source/ddbus/conv.d +++ b/source/ddbus/conv.d @@ -1,9 +1,11 @@ module ddbus.conv; +import ddbus.attributes : isAllowedField; import ddbus.c_lib; import ddbus.exception : InvalidValueException, TypeMismatchException; import ddbus.util; import ddbus.thin; + import std.exception : enforce; import std.meta: allSatisfy; import std.string; @@ -350,65 +352,6 @@ void readIterStruct(S)(DBusMessageIter *iter, ref S s) if(is(S == struct) && all } } -/++ - Flags for use with dbusMarshaling UDA - - Default is to include public fields only -+/ -enum MarshalingFlag : ubyte { - includePrivateFields = 1 << 0, /// Automatically include private fields - manualOnly = 1 << 7 /// Only include fields with explicit - /// `@Yes.DBusMarshal`. This overrides any - /// `include` flags. -} - -private template isMarshalingFlag(T) { - enum isMarshalingFlag = is(T == MarshalingFlag); -} - -/++ - UDA for specifying DBus marshaling options on structs -+/ -auto dbusMarshaling(Args)(Args args ...) - if (allSatisfy!(isMarshalingFlag, Args)) { - return BitFlags!MarshalingFlag(args); -} - -private template marshalingFlags(S) if (is(S == struct)) { - private alias getUDAs!(S, BitFlags!MarshalingFlag) UDAs; - - static if (UDAs.length == 0) - enum marshalingFlags = BitFlags!MarshalingFlag.init; - else { - static assert (UDAs.length == 1, - "Only one @dbusMarshaling UDA allowed on type."); - static assert (is(typeof(UDAs[0]) == BitFlags!MarshalingFlag), - "Huh? Did you intend to use @dbusMarshaling UDA?"); - enum marshalingFlags = UDAs[0]; - } -} - -private template isAllowedField(alias field) { - private enum flags = marshalingFlags!(__traits(parent, field)); - private alias getUDAs!(field, Flag!"DBusMarshal") UDAs; - - static if (UDAs.length != 0) { - static assert (UDAs.length == 1, - "Only one UDA of type Flag!\"DBusMarshal\" allowed on struct field."); - static assert (is(typeof(UDAs[0]) == Flag!"DBusMarshal"), - "Did you intend to add UDA Yes.DBusMarshal or No.DBusMarshal?"); - enum isAllowedField = cast(bool) UDAs[0]; - } else static if (!(flags & MarshalingFlag.manualOnly)) { - static if (__traits(getProtection, field) == "public") - enum isAllowedField = true; - else static if (cast(bool) (flags & MarshalingFlag.includePrivateFields)) - enum isAllowedField = true; - else - enum isAllowedField = false; - } else - enum isAllowedField = false; -} - unittest { import dunit.toolkit; import ddbus.thin; diff --git a/source/ddbus/package.d b/source/ddbus/package.d index 16bf848..ba0b271 100644 --- a/source/ddbus/package.d +++ b/source/ddbus/package.d @@ -2,3 +2,4 @@ public import ddbus.thin; public import ddbus.router; public import ddbus.bus; public import ddbus.simple; +public import ddbus.attributes; diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index c98527e..31ca7c5 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -572,6 +572,7 @@ struct Connection { unittest { import dunit.toolkit; + import ddbus.attributes : dbusMarshaling, MarshalingFlag; struct S1 { private int a;