1 module ddparser.serialize; 2 3 import std.traits; 4 import std.json; 5 import std.string; 6 import core.stdc.string; 7 import std.stdio; 8 9 template fieldMap(string field, alias s) 10 { 11 enum fieldMap = ` 12 if ( ` ~ s.stringof ~ `.serializing) 13 { 14 ` ~ s.stringof ~ `.currentObject["` ~ field ~ `"] = ` ~ s.stringof ~ `.serializeValue(` ~ field ~ `); 15 } 16 else 17 { 18 typeof(` ~ field ~ `) f; 19 ` ~ s.stringof ~ `.deserializeValue(f, ` ~ s.stringof ~ `.currentObject["` ~ field ~ `"]); 20 ` ~ field ~ ` = f; 21 } 22 `; 23 } 24 25 class Serializer 26 { 27 JSONValue serialize(T)(ref T v) 28 { 29 objects = null; 30 indexes = null; 31 currentObject = null; 32 33 serializing = true; 34 JSONValue rootObject = serializeValue(v); 35 return JSONValue(["root" : rootObject, "objects" : JSONValue(objects)]); 36 } 37 38 void deserialize(T)(ref T v, in JSONValue val) 39 { 40 currentObject = null; 41 42 serializing = false; 43 objects = val["objects"].array.dup; 44 pointers = new void*[objects.length]; 45 deserializeValue(v, val["root"]); 46 } 47 48 49 void map(T)(ref T v, string name) 50 { 51 if (serializing) 52 { 53 currentObject[name] = serializeValue(v); 54 } 55 else 56 { 57 try 58 { 59 deserializeValue(v, currentObject[name]); 60 } 61 catch(Exception e) 62 { 63 writeln("Could not deserialize: ", name); 64 throw e; 65 } 66 67 } 68 } 69 70 void mapCString(ref char* v, string name) 71 { 72 if (serializing) 73 { 74 currentObject[name] = serializeCString(v); 75 } 76 else 77 { 78 v = deserializeCString(currentObject[name]); 79 } 80 } 81 82 void mapCArray(T, L)(ref T* v, string arrName, ref L len) 83 { 84 if (serializing) 85 { 86 JSONValue[] arr; 87 foreach(i; v[0 .. len]) 88 { 89 arr ~= serializeValue(i); 90 } 91 92 currentObject[arrName] = JSONValue(arr); 93 } 94 else 95 { 96 auto desArr = currentObject[arrName].array; 97 len = cast(L)desArr.length; 98 T[] arr = new T[len]; 99 for (int i = 0; i < len; ++i) 100 { 101 deserializeValue(arr[i], desArr[i]); 102 } 103 v = arr.ptr; 104 } 105 } 106 107 void mapCStringWithLength(L)(ref char* v, string name, ref L len) 108 { 109 if (serializing) 110 { 111 currentObject[name] = JSONValue(cast(string)v[0 .. len]); 112 } 113 else 114 { 115 string val = currentObject[name].str; 116 v = cast(char*)val.dup.toStringz(); 117 len = cast(L)val.length; 118 } 119 } 120 121 JSONValue serializeCString(const char* v) 122 { 123 if (!v) return JSONValue(null); 124 uint* index = v in indexes; 125 if (index) return JSONValue(*index); 126 objects ~= JSONValue(cast(string)v[0 .. strlen(v)]); 127 uint result = cast(uint)objects.length - 1; 128 indexes[v] = result; 129 return JSONValue(result); 130 } 131 132 char* deserializeCString(JSONValue j) 133 { 134 if (j.type == JSON_TYPE.NULL) return null; 135 auto index = j.uinteger; 136 char* result = cast(char*)pointers[index]; 137 if (!result) 138 { 139 result = cast(char*)objects[index].str.toStringz(); 140 pointers[index] = result; 141 } 142 return result; 143 } 144 145 JSONValue serializePointer(T)(ref T v) 146 { 147 if (v == null) return JSONValue(null); 148 uint* index = v in indexes; 149 if (index) return JSONValue(*index); 150 uint result = cast(uint)objects.length; 151 indexes[v] = result; 152 objects ~= JSONValue(null); 153 objects[result] = serializeValue(*v); 154 return JSONValue(result); 155 } 156 157 void deserializePointer(T)(ref T v, JSONValue j) 158 { 159 if (j.type == JSON_TYPE.NULL) 160 { 161 v = null; 162 return; 163 } 164 auto index = j.uinteger; 165 v = cast(T)pointers[index]; 166 if (!v) 167 { 168 v = new typeof(*v)(); 169 pointers[index] = v; 170 deserializeValue(*v, objects[index]); 171 } 172 } 173 174 JSONValue serializeValue(T)(in T v) if (isNumeric!T || isBoolean!T) 175 { 176 return JSONValue(v); 177 } 178 179 JSONValue serializeValue(T)(ref T v) if (!isNumeric!T && !isBoolean!T) 180 { 181 static if (isPointer!T) 182 { 183 static if (is(Unqual!T == char*)) 184 { 185 return serializeCString(v); 186 } 187 else static if (is(Unqual!T == void*)) 188 { 189 assert(false); 190 } 191 else 192 { 193 return serializePointer(v); 194 } 195 } 196 else static if (is(T == struct)) 197 { 198 static if (__traits(hasMember, T, "customSerialize")) 199 { 200 return v.customSerialize(this); 201 } 202 else static if (__traits(hasMember, T, "serialize")) 203 { 204 auto oldObject = currentObject; 205 currentObject = null; 206 v.serialize(this); 207 auto res = currentObject; 208 currentObject = oldObject; 209 return JSONValue(res); 210 } 211 else 212 { 213 return JSONValue("ERROR!!!"); 214 } 215 } 216 else static if (isArray!T) 217 { 218 JSONValue[] arr; 219 foreach(i; v) 220 { 221 arr ~= serializeValue(i); 222 } 223 return JSONValue(arr); 224 } 225 } 226 227 void deserializeValue(T)(ref T v, JSONValue j) 228 { 229 static if (isIntegral!T) 230 { 231 static if (isSigned!T) 232 v = cast(T)j.integer; 233 else 234 v = cast(T)j.uinteger; 235 } 236 else static if (isBoolean!T) 237 { 238 v = cast(bool)j.uinteger; 239 } 240 else static if (isFloatingPoint!T) 241 { 242 v = cast(T)j.floating; 243 } 244 else static if (isPointer!T) 245 { 246 static if (is(Unqual!T == char*)) 247 { 248 v = deserializeCString(j); 249 } 250 else static if (is(Unqual!T == void*)) 251 { 252 assert(false); 253 } 254 else 255 { 256 deserializePointer(v, j); 257 } 258 } 259 else static if (is(T == struct)) 260 { 261 static if (__traits(hasMember, T, "customDeserialize")) 262 { 263 v.customDeserialize(this, j); 264 } 265 else static if (__traits(hasMember, T, "serialize")) 266 { 267 auto oldObj = currentObject; 268 currentObject = j.object; 269 v.serialize(this); 270 currentObject = oldObj; 271 } 272 else 273 { 274 275 } 276 } 277 else static if (isArray!T) 278 { 279 280 } 281 } 282 283 bool serializing; 284 JSONValue[] objects; 285 uint[void*] indexes; 286 void*[] pointers; 287 JSONValue[string] currentObject; 288 } 289 290