Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions source/mir/reflection.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,31 @@
module mir.reflection;

import std.meta;
import std.traits: Parameters, isSomeFunction, FunctionAttribute, functionAttributes;
import std.traits: getUDAs, Parameters, isSomeFunction, FunctionAttribute, functionAttributes;

/++
Checks if member is field.
Returns: single UDA.
+/
template isField(T, string member)
template getUDA(alias symbol, alias attribute)
{
T aggregate;
enum bool isField = __traits(compiles, __traits(getMember, aggregate, member).offsetof);
private alias all = getUDAs!(symbol, attribute);
static if (all.length != 1)
static assert(0, "Exactly one " ~ attribute.stringof ~ " attribute is required");
else
{
static if (is(typeof(all[0])))
enum getUDA = all[0];
else
alias getUDA = all[0];
}
}

/++
Checks if member is field.
+/
enum bool isField(T, string member) = __traits(compiles, (ref T aggregate) { return __traits(getMember, aggregate, member).offsetof; });


///
version(mir_test)
unittest
Expand Down
56 changes: 46 additions & 10 deletions source/mir/serde.d
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
module mir.serde;

import std.traits: getUDAs, hasUDA;

private template getUDA(alias symbol, alias attribute)
{
private alias all = getUDAs!(symbol, attribute);
static assert(all.length == 1, "Exactly one " ~ attribute.stringof ~ " attribute is allowed");
enum getUDA = all[0];
}
import mir.reflection: getUDA;
import std.traits: hasUDA, TemplateArgsOf;

/++
Attribute for key overloading during Serialization and Deserialization.
Expand Down Expand Up @@ -250,13 +244,17 @@ unittest
double d;
}

import std.traits: hasUDA, getUDAs;
import std.traits: hasUDA;

static assert(hasUDA!(S.d, serdeProxy));
static assert(hasUDA!(S.d, serdeProxy!(SmallString!32)));
static assert(getUDAs!(S.d, serdeProxy).length == 1);
static assert(is(serdeGetProxy!(S.d) == SmallString!32));
}

/++
+/
alias serdeGetProxy(alias symbol) = TemplateArgsOf!(getUDA!(symbol, serdeProxy))[0];

/++
Can be applied only to fields that can be constructed from strings.
Does not allocate new data when deserializeing. Raw data is used for strings instead of new memory allocation.
Expand Down Expand Up @@ -380,3 +378,41 @@ unittest
static assert(hasSerdeIgnoreCase(E.c));
static assert(hasSerdeIgnoreCase(E.d));
}

/++
Can be applied only to strings fields.
Does not allocate new data when deserializeing. Raw ASDF data is used for strings instead of new memory allocation.
Use this attributes only for strings that would not be used after ASDF deallocation.
+/
enum serdeScoped;

/++
Attribute that force deserializer to throw an exception that the field was not found in the input.
+/
enum serdeRequired;


/++
Attributes for in transformation.
Return type of in transformation must be implicitly convertable to the type of the field.
In transformation would be applied after serialization proxy if any.

+/
struct serdeTransformIn(alias fun) {}

/++
Returns: unary function of underlaying alias of $(LREF serdeTransformIn)
+/
alias serdeGetTransformIn(alias value) = unaryFun!(TemplateArgsOf!(getUDA!(value, serdeTransformIn))[0]);

/++
Attributes for out transformation.
Return type of out transformation may be differ from the type of the field.
Out transformation would be applied before serialization proxy if any.
+/
struct serdeTransformOut(alias fun) {}

/++
Returns: unary function of underlaying alias of $(LREF serdeTransformOut)
+/
alias serdeGetTransformOut(alias value) = unaryFun!(TemplateArgsOf!(getUDA!(value, serdeTransformOut))[0]);