Skip to content

Instantly share code, notes, and snippets.

@s-ludwig
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save s-ludwig/18679e92267cbef764e5 to your computer and use it in GitHub Desktop.
Save s-ludwig/18679e92267cbef764e5 to your computer and use it in GitHub Desktop.
vibe.data.serialization module for sdlang-d
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