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