Skip to content

Commit

Permalink
Merge pull request #2001 from vibe-d/issue_1991_system_property_seria…
Browse files Browse the repository at this point in the history
…lization

Work around compile error in the serialization system. Fixes #1991.
  • Loading branch information
s-ludwig authored Dec 22, 2017
2 parents b87ebd2 + 5071ea1 commit a49cff0
Showing 1 changed file with 48 additions and 4 deletions.
52 changes: 48 additions & 4 deletions data/vibe/data/serialization.d
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,14 @@ private template serializeValueImpl(Serializer, alias Policy) {
return;
}
}
static auto safeGetMember(string mname)(ref T val) @safe {
static if (__traits(compiles, __traits(getMember, val, mname))) {
return __traits(getMember, val, mname);
} else {
pragma(msg, "Warning: Getter for "~fullyQualifiedName!T~"."~mname~" is not @safe");
return () @trusted { return __traits(getMember, val, mname); } ();
}
}
static if (hasPolicyAttributeL!(AsArrayAttribute, Policy, ATTRIBUTES)) {
enum nfields = getExpandedFieldCount!(TU, SerializableFields!(TU, Policy));
ser.beginWriteArray!Traits(nfields);
Expand All @@ -494,7 +502,10 @@ private template serializeValueImpl(Serializer, alias Policy) {
alias TA = TypeTuple!(__traits(getAttributes, TypeTuple!(__traits(getMember, T, mname))[j]));
alias STraits = SubTraits!(Traits, TM, TA);
ser.beginWriteArrayEntry!STraits(fcount);
ser.serializeValue!(TM, TA)(tuple(__traits(getMember, value, mname))[j]);
static if (TMS.length == 1)
ser.serializeValue!(TM, TA)(safeGetMember!mname(value));
else
ser.serializeValue!(TM, TA)(tuple(__traits(getMember, value, mname))[j]);
ser.endWriteArrayEntry!STraits(fcount);
fcount++;
}
Expand All @@ -512,7 +523,7 @@ private template serializeValueImpl(Serializer, alias Policy) {
alias TA = TypeTuple!(__traits(getAttributes, TypeTuple!(__traits(getMember, T, mname))[0]));
enum name = getPolicyAttribute!(TU, mname, NameAttribute, Policy)(NameAttribute!DefaultPolicy(underscoreStrip(mname))).name;
static if (TM.length == 1) {
auto vt = __traits(getMember, value, mname);
auto vt = safeGetMember!mname(value);
} else {
auto vt = tuple!TM(__traits(getMember, value, mname));
}
Expand Down Expand Up @@ -715,6 +726,16 @@ private template deserializeValueImpl(Serializer, alias Policy) {
bool[getExpandedFieldsData!(T, SerializableFields!(T, Policy)).length] set;
static if (is(T == class)) ret = new T;

void safeSetMember(string mname, U)(ref T value, U fval)
@safe {
static if (__traits(compiles, () @safe { __traits(getMember, value, mname) = fval; }))
__traits(getMember, value, mname) = fval;
else {
pragma(msg, "Warning: Setter for "~fullyQualifiedName!T~"."~mname~" is not @safe");
() @trusted { __traits(getMember, value, mname) = fval; } ();
}
}

static if (hasPolicyAttributeL!(AsArrayAttribute, Policy, ATTRIBUTES)) {
size_t idx = 0;
ser.readArray!Traits((sz){}, {
Expand All @@ -736,7 +757,7 @@ private template deserializeValueImpl(Serializer, alias Policy) {
set[i] = true;
ser.beginReadArrayEntry!STraits(i);
static if (MT.length == 1) {
__traits(getMember, ret, mname) = ser.deserializeValue!(TMTI, TMTIA);
safeSetMember!mname(ret, ser.deserializeValue!(TMTI, TMTIA));
} else {
__traits(getMember, ret, mname)[msindex] = ser.deserializeValue!(TMTI, TMTIA);
}
Expand Down Expand Up @@ -764,7 +785,7 @@ private template deserializeValueImpl(Serializer, alias Policy) {
set[i] = true;
ser.beginReadDictionaryEntry!STraits(fname);
static if (TM.length == 1) {
__traits(getMember, ret, mname) = ser.deserializeValue!(TM, TA);
safeSetMember!mname(ret, ser.deserializeValue!(TM, TA));
} else {
__traits(getMember, ret, mname) = ser.deserializeValue!(Tuple!TM, TA);
}
Expand Down Expand Up @@ -1896,3 +1917,26 @@ unittest {
auto deser = deserialize!(TestSerializer, S)(ser);
assert(deser.bar_ == 42);
}

@safe unittest { // issue 1941
static struct Bar { Bar[] foos; int i; }
Bar b1 = {[{null, 2}], 1};
auto s = serialize!TestSerializer(b1);
auto b = deserialize!(TestSerializer, Bar)(s);
assert(b.i == 1);
assert(b.foos.length == 1);
assert(b.foos[0].i == 2);
}

unittest { // issue 1991 - @system property getters/setters does not compile
static class A {
@property @name("foo") {
string fooString() const { return "a"; }
void fooString(string a) { }
}
}

auto a1 = new A;
auto b = serialize!TestSerializer(a1);
auto a2 = deserialize!(TestSerializer, A)(b);
}

0 comments on commit a49cff0

Please sign in to comment.