Move UDA stuff for struct support to separate module

This commit is contained in:
Harry T. Vennik 2017-09-30 15:49:58 +02:00
parent 89c7736ccf
commit 9bbd4a3bbf
3 changed files with 68 additions and 59 deletions

65
source/ddbus/attributes.d Normal file
View file

@ -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];
}
}

View file

@ -1,9 +1,11 @@
module ddbus.conv; module ddbus.conv;
import ddbus.attributes : isAllowedField;
import ddbus.c_lib; import ddbus.c_lib;
import ddbus.exception : InvalidValueException, 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;
import std.meta: allSatisfy; import std.meta: allSatisfy;
import std.string; 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 { unittest {
import dunit.toolkit; import dunit.toolkit;
import ddbus.thin; import ddbus.thin;

View file

@ -572,6 +572,7 @@ struct Connection {
unittest { unittest {
import dunit.toolkit; import dunit.toolkit;
import ddbus.attributes : dbusMarshaling, MarshalingFlag;
struct S1 { struct S1 {
private int a; private int a;