Last active
August 29, 2015 14:05
-
-
Save s-ludwig/18679e92267cbef764e5 to your computer and use it in GitHub Desktop.
vibe.data.serialization module for sdlang-d
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sdlang.Tag serializeSDL(T)(T value) | |
{ | |
import vibe.data.serialization; | |
return serialize!SDLSerializer(value); | |
} | |
T deserializeSDL(T)(sdlang.Tag root) | |
{ | |
return deserialize!(SDLSerializer, T)(root); | |
} | |
struct SDLSerializer { | |
import std.traits; | |
import std.typetuple; | |
enum useAttributes = false; | |
template isSDLValueType(T) { enum isSDLValueType = staticIndexOf!(T, sdlang.ValueTypes) >= 0; } | |
template isSupportedValueType(T) { enum isSupportedValueType = isSDLValueType!T || is(T == sdlang.Value) || is(T == sdlang.Tag); } | |
private { | |
sdlang.Tag m_current; | |
sdlang.Tag[] m_compositeStack; | |
} | |
this(sdlang.Tag data) { m_current = data; } | |
@disable this(this); | |
// | |
// serialization | |
// | |
sdlang.Tag getSerializedResult() { return m_current; } | |
void beginWriteDictionary(T)() { m_compositeStack ~= new sdlang.Tag; } | |
void endWriteDictionary(T)() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; } | |
void beginWriteDictionaryEntry(T)(string name) {} | |
void endWriteDictionaryEntry(T)(string name) { | |
static if (isSDLValueType!T && useAttributes) { | |
assert(m_current.values.length == 1); | |
m_compositeStack[$-1].add(new sdlang.Attribute(name, m_current.values[0])); | |
} else { | |
m_current.name = name; | |
m_compositeStack[$-1].add(m_current); | |
} | |
} | |
void beginWriteArray(T)(size_t) { m_compositeStack ~= new sdlang.Tag; } | |
void endWriteArray(T)() | |
{ | |
m_current = m_compositeStack[$-1]; | |
m_compositeStack.length--; | |
} | |
void beginWriteArrayEntry(T)(size_t) {} | |
void endWriteArrayEntry(T)(size_t) { | |
static if (isSDLValueType!T) { | |
assert(m_current.values.length == 1); | |
m_compositeStack[$-1].add(m_current.values[0]); | |
} else { | |
m_compositeStack[$-1].add(m_current); | |
if (!m_current.values.length && !m_current.name.length) | |
m_current.name = "entry"; | |
} | |
} | |
void writeValue(T)(T value) | |
{ | |
static if (isSDLValueType!T) { | |
m_current = new sdlang.Tag; | |
m_current.add(sdlang.Value(value)); | |
} else static if (is(T == sdlang.Value)) { | |
m_current = new sdlang.Tag; | |
m_current.add(value); | |
} else static if (is(T == sdlang.Tag)) m_current = value; | |
else static assert(false, "Unsupported SDL value type: "~T.stringof); | |
} | |
// | |
// deserialization | |
// | |
void readDictionary(T)(scope void delegate(string) field_handler) | |
{ | |
auto old = m_current; | |
scope (success) m_current = old; | |
static if (useAttributes && isAssociativeArray!T && isSDLValueType!(ValueType!T)) { | |
foreach (att; old.attributes) { | |
m_current = new sdlang.Tag; | |
m_current.add(att.value); | |
field_handler(att.name); | |
} | |
} else { | |
foreach (tag; old.tags) { | |
m_current = tag; | |
field_handler(tag.name); | |
} | |
} | |
} | |
void readArray(T)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback) | |
{ | |
auto old = m_current; | |
scope (success) m_current = old; | |
size_callback(old.values.length + old.tags.length); | |
foreach (v; old.values) { | |
m_current = new sdlang.Tag; | |
m_current.add(v); | |
entry_callback(); | |
} | |
foreach (t; old.tags) { | |
m_current = t; | |
entry_callback(); | |
} | |
} | |
T readValue(T)() | |
{ | |
static if (isSDLValueType!T) return m_current.values[0].get!T(); | |
else static if (is(T == sdlang.Value)) return m_current.values[0]; | |
else static if (is(T == sdlang.Tag)) return m_current; | |
else static assert(false, "Unsupported SDL value type: "~T.stringof); | |
} | |
bool tryReadNull() { return m_current.values[0].peek!(typeof(null)) !is null; } | |
} | |
version(unittest) { | |
private static void assertSame(sdlang.Tag a, string source) | |
{ | |
auto astr = a.toSDLDocument(); | |
assert(astr == source, astr); | |
} | |
} | |
unittest { | |
static struct S { | |
int integer; | |
float fpoint; | |
string str; | |
double dbl; | |
int[] intarray; | |
int[string] intattribs; | |
} | |
auto s = S(1, 2.0, "3", 4.0, [5, 6, 7], ["a": 8, "b": 9]); | |
auto res = serializeSDL(s); | |
assertSame(res, | |
`integer 1 | |
fpoint 2F | |
str "3" | |
dbl 4D | |
intarray 5 6 7 | |
intattribs { | |
a 8 | |
b 9 | |
} | |
`); | |
S sd = deserializeSDL!S(res); | |
import std.conv; | |
assert(sd == s, sd.to!string()); | |
} | |
unittest { | |
static struct T { int i; string j; } | |
static struct S { | |
T[] uarr; | |
T[string] udict; | |
} | |
auto s = S([T(1, "2"), T(3, "4")], ["a": T(5, "6"), "b": T(7, "8")]); | |
auto res = serializeSDL(s); | |
assertSame(res, | |
`uarr { | |
entry { | |
i 1 | |
j "2" | |
} | |
entry { | |
i 3 | |
j "4" | |
} | |
} | |
udict { | |
a { | |
i 5 | |
j "6" | |
} | |
b { | |
i 7 | |
j "8" | |
} | |
} | |
`); | |
auto sd = deserializeSDL!S(res); | |
import std.conv; | |
assert(sd == s, sd.to!string); | |
} | |
unittest { | |
static struct T { int i; string j; } | |
static struct S { | |
@asArray T[] uarr; | |
@asArray T[string] udict; | |
} | |
auto s = S([T(1, "2"), T(3, "4")], ["a": T(5, "6"), "b": T(7, "8")]); | |
auto res = serializeSDL(s); | |
assertSame(res, | |
`uarr { | |
1 "2" | |
3 "4" | |
} | |
udict { | |
a 5 "6" | |
b 7 "8" | |
} | |
`); | |
auto sd = deserializeSDL!S(res); | |
import std.conv; | |
assert(sd == s, sd.to!string); | |
} | |
unittest { | |
assertSame((new sdlang.Tag).add(serializeSDL(1)), "1\n"); | |
assertSame(serializeSDL(["a": 1, "b": 2]), "a 1\nb 2\n"); | |
assertSame((new sdlang.Tag).add(serializeSDL([1, 2])), "1 2\n"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment