醜いハックの塊。
その一: 戻り値に静的配列が使えない。
その二: Struct.tupleofをforeachした要素がコピーになってる。
その三: テンプレート+オーバーロードの問題(これは仕方ない気もするが)。
/** * Author: Nazo * License: Public Domain */ module nazo.serialize; /** * シリアライズします。 * Bugs: ポインタ/連想配列/float/double/realなどに未対応 * Bugs: Tからrvの長さが一意に決まるのでそれを使うべし。 */ ubyte[] serialize(T)(T t){ ubyte[] rv; static if(is(T==struct)){ foreach(x;t.tupleof) rv~=serialize(x); }else static if(__traits(isIntegral,T)){ rv=(cast(ubyte*)[t].ptr)[0..T.sizeof]; }else static if(__traits(isStaticArray,T)){ rv=cast(ubyte[])t; }else static if(is(T U:U[])){ rv=serialize(t.length) ~ cast(ubyte[])t; }else{ assert(0,"unsupported"); } return rv; } template ReturnType(T){ static if(__traits(isStaticArray,T) && is(T U:U[])){ alias U[] ReturnType; }else{ alias T ReturnType; } } /** * デシリアライズします。 * Bugs: ポインタ/連想配列/float/double/realなどに未対応 */ ReturnType!(T) deserialize(T)(ubyte[] t){ ubyte* ptr = t.ptr; return _deserialize!(T)(ptr); } private ReturnType!(T) _deserialize(T)(ref ubyte* t){ ReturnType!(T) rv; static if(is(T==struct)){ foreach(i,x;rv.tupleof){ static if(__traits(isStaticArray,typeof(x))) rv.tupleof[i][]/*x[]=*/=_deserialize!(typeof(x))(t)[]; else rv.tupleof[i]/*x=*/=_deserialize!(typeof(x))(t); } }else static if(__traits(isIntegral,T)){ rv=*cast(T*)t; t+=T.sizeof; }else static if(__traits(isStaticArray,T)&&is(T U:U[])){ rv=cast(U[])t[0..T.sizeof]; t+=T.sizeof; }else static if(is(T U:U[])){ int len = _deserialize!(size_t)(t); rv= (cast(U*)t)[0..len]; t+=len*U.sizeof; }else{ assert(0,"unsupported"); } return rv; } import std.stdio; struct Test{ ubyte a; uint b; ubyte[2] c; ubyte[] d; string[] e; } void main(){ ubyte[] data; Test test=Test(2,10,2,[3,4],["1","2"]); writefln(test.tupleof); data=serialize(test); writefln(data); test=deserialize!(Test)(data); writefln(test.tupleof); }