Skip to content

Commit

Permalink
Add (begin/end)Write(Dictionary/Array)Entry serializer methods.
Browse files Browse the repository at this point in the history
This enables the deserializer to access field attributes and other useful information.
  • Loading branch information
s-ludwig committed Aug 5, 2016
1 parent 8b04bab commit abbf07d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
6 changes: 6 additions & 0 deletions source/vibe/data/bson.d
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,9 @@ struct BsonSerializer {
m_inputData = old;
}

void beginReadDictionaryEntry(Traits)(string name) {}
void endReadDictionaryEntry(Traits)(string name) {}

void readArray(Traits)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback)
{
enforce(m_inputData.type == Bson.Type.array, "Expected array instead of "~m_inputData.type.to!string());
Expand All @@ -1450,6 +1453,9 @@ struct BsonSerializer {
m_inputData = old;
}

void beginReadArrayEntry(Traits)(size_t index) {}
void endReadArrayEntry(Traits)(size_t index) {}

T readValue(Traits, T)()
{
static if (is(T == Bson)) return m_inputData;
Expand Down
12 changes: 12 additions & 0 deletions source/vibe/data/json.d
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,9 @@ struct JsonSerializer {
m_current = old;
}

void beginReadDictionaryEntry(Traits)(string name) {}
void endReadDictionaryEntry(Traits)(string name) {}

void readArray(Traits)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback)
{
enforceJson(m_current.type == Json.Type.array, "Expected JSON array, got "~m_current.type.to!string);
Expand All @@ -1621,6 +1624,9 @@ struct JsonSerializer {
m_current = old;
}

void beginReadArrayEntry(Traits)(size_t index) {}
void endReadArrayEntry(Traits)(size_t index) {}

T readValue(Traits, T)()
{
static if (is(T == Json)) return m_current;
Expand Down Expand Up @@ -1778,6 +1784,9 @@ struct JsonStringSerializer(R, bool pretty = false)
}
}

void beginReadDictionaryEntry(Traits)(string name) {}
void endReadDictionaryEntry(Traits)(string name) {}

void readArray(Traits)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback)
{
m_range.skipWhitespace(&m_line);
Expand All @@ -1799,6 +1808,9 @@ struct JsonStringSerializer(R, bool pretty = false)
}
}

void beginReadArrayEntry(Traits)(size_t index) {}
void endReadArrayEntry(Traits)(size_t index) {}

T readValue(Traits, T)()
{
m_range.skipWhitespace(&m_line);
Expand Down
39 changes: 35 additions & 4 deletions source/vibe/data/serialization.d
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,12 @@
void writeValue(TypeTraits, T)(T value);
// deserialization
void readDictionary(ElementTypeTraits)(scope void delegate(string) entry_callback);
void readArray(ElementTypeTraits)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback);
void readDictionary(TypeTraits, alias on_entry)();
void beginReadDictionaryEntry(ElementTypeTraits)(string);
void endReadDictionaryEntry(ElementTypeTraits)(string);
void readArray(TypeTraits, alias on_size, alias on_entry)();
void beginReadArrayEntry(ElementTypeTraits)(size_t index);
void endReadArrayEntry(ElementTypeTraits)(size_t index);
T readValue(TypeTraits, T)();
bool tryReadNull(TypeTraits)();
}
Expand Down Expand Up @@ -508,24 +512,33 @@ private template deserializeValueImpl(Serializer, alias Policy) {
return ser.readValue!(Traits, T)();
} else static if (isStaticArray!T) {
alias TV = typeof(T.init[0]);
alias STraits = SubTraits!(Traits, TV);
T ret;
size_t i = 0;
ser.readArray!Traits((sz) { assert(sz == 0 || sz == T.length); }, {
assert(i < T.length);
ret[i++] = ser.deserializeValue!(TV, ATTRIBUTES);
ser.beginReadArrayEntry!STraits(i);
ret[i] = ser.deserializeValue!(TV, ATTRIBUTES);
ser.endReadArrayEntry!STraits(i);
i++;
});
return ret;
} else static if (isDynamicArray!T) {
alias TV = typeof(T.init[0]);
alias STraits = SubTraits!(Traits, TV);
//auto ret = appender!T();
T ret; // Cannot use appender because of DMD BUG 10690/10859/11357
ser.readArray!Traits((sz) { ret.reserve(sz); }, () {
size_t i = ret.length;
ser.beginReadArrayEntry!STraits(i);
ret ~= ser.deserializeValue!(TV, ATTRIBUTES);
ser.endReadArrayEntry!STraits(i);
});
return ret;//cast(T)ret.data;
} else static if (isAssociativeArray!T) {
alias TK = KeyType!T;
alias TV = ValueType!T;
alias STraits = SubTraits!(Traits, TV);

T ret;
ser.readDictionary!Traits((name) {
Expand All @@ -534,16 +547,23 @@ private template deserializeValueImpl(Serializer, alias Policy) {
else static if (is(TK : real) || is(TK : long) || is(TK == enum)) key = name.to!TK;
else static if (isStringSerializable!TK) key = TK.fromString(name);
else static assert(false, "Associative array keys must be strings, numbers, enums, or have toString/fromString methods.");
ser.beginReadDictionaryEntry!STraits(name);
ret[key] = ser.deserializeValue!(TV, ATTRIBUTES);
ser.endReadDictionaryEntry!STraits(name);
});
return ret;
} else static if (isInstanceOf!(Nullable, T)) {
if (ser.tryReadNull!Traits()) return T.init;
return T(ser.deserializeValue!(typeof(T.init.get()), ATTRIBUTES));
} else static if (__VERSION__ >= 2067 && is(T == BitFlags!E, E)) {
alias STraits = SubTraits!(Traits, E);
T ret;
size_t i = 0;
ser.readArray!Traits((sz) {}, {
ser.beginReadArrayEntry!STraits(i);
ret |= ser.deserializeValue!(E, ATTRIBUTES);
ser.endReadArrayEntry!STraits(i);
i++;
});
return ret;
} else static if (isCustomSerializable!T) {
Expand Down Expand Up @@ -572,11 +592,14 @@ private template deserializeValueImpl(Serializer, alias Policy) {
foreach (i, mname; SerializableFields!(T, Policy)) {
alias TM = typeof(__traits(getMember, ret, mname));
alias TA = TypeTuple!(__traits(getAttributes, __traits(getMember, ret, mname)));
alias STraits = SubTraits!(Traits, TM, TA);
case i:
static if (hasPolicyAttribute!(OptionalAttribute, Policy, __traits(getMember, T, mname)))
if (ser.tryReadNull!SubTraits()) return;
set[i] = true;
ser.beginReadArrayEntry!STraits(i);
__traits(getMember, ret, mname) = ser.deserializeValue!(TM, TA);
ser.endReadArrayEntry!STraits(i);
break;
}
}
Expand All @@ -592,13 +615,15 @@ private template deserializeValueImpl(Serializer, alias Policy) {
foreach (i, mname; SerializableFields!(T, Policy)) {
alias TM = typeof(__traits(getMember, ret, mname));
alias TA = TypeTuple!(__traits(getAttributes, __traits(getMember, ret, mname)));
enum fname = getPolicyAttribute!(T, mname, NameAttribute, Policy)(NameAttribute!DefaultPolicy(underscoreStrip(mname))).name;
alias STraits = SubTraits!(Traits, TM, TA);
enum fname = getPolicyAttribute!(T, mname, NameAttribute, Policy)(NameAttribute!DefaultPolicy(underscoreStrip(mname))).name;
case fname:
static if (hasPolicyAttribute!(OptionalAttribute, Policy, __traits(getMember, T, mname)))
if (ser.tryReadNull!STraits()) return;
set[i] = true;
ser.beginReadDictionaryEntry!STraits(fname);
__traits(getMember, ret, mname) = ser.deserializeValue!(TM, TA);
ser.endReadDictionaryEntry!STraits(fname);
break;
}
}
Expand Down Expand Up @@ -1143,6 +1168,9 @@ version (unittest) {
skip("}D("~Traits.Type.mangleof~")");
}

void beginReadDictionaryEntry(Traits)(string name) {}
void endReadDictionaryEntry(Traits)(string name) {}

void readArray(Traits)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback)
{
skip("A("~Traits.Type.mangleof~")[");
Expand Down Expand Up @@ -1170,6 +1198,9 @@ version (unittest) {
assert(i == cnt);
}

void beginReadArrayEntry(Traits)(size_t index) {}
void endReadArrayEntry(Traits)(size_t index) {}

T readValue(Traits, T)()
{
skip("V("~T.mangleof~")(");
Expand Down

0 comments on commit abbf07d

Please sign in to comment.