Mercurial > projects > orange
annotate orange/serialization/Serializer.d @ 18:3d42ea434d46
Added an error callback. Fixes #3 and #4.
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Thu, 12 Aug 2010 23:24:51 +0200 |
parents | c4e7e64ffb67 |
children | 9a575087b961 |
rev | line source |
---|---|
0 | 1 /** |
2 * Copyright: Copyright (c) 2010 Jacob Carlborg. | |
3 * Authors: Jacob Carlborg | |
4 * Version: Initial created: Jan 26, 2010 | |
5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) | |
6 */ | |
7 module orange.serialization.Serializer; | |
8 | |
9 version (Tango) | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
8
diff
changeset
|
10 import tango.util.Convert : to, ConversionException; |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
8
diff
changeset
|
11 |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
8
diff
changeset
|
12 else |
0 | 13 { |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
8
diff
changeset
|
14 import std.conv; |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
8
diff
changeset
|
15 alias ConvError ConversionException; |
0 | 16 } |
17 | |
18 import orange.serialization._; | |
19 import orange.serialization.archives._; | |
20 import orange.util._; | |
21 | |
22 private | |
23 { | |
24 alias orange.util.CTFE.contains ctfeContains; | |
25 | |
26 private enum Mode | |
27 { | |
28 serializing, | |
29 deserializing | |
30 } | |
31 | |
32 alias Mode.serializing serializing; | |
33 alias Mode.deserializing deserializing; | |
34 } | |
35 | |
36 class Serializer (ArchiveType : IArchive) | |
37 { | |
38 static assert(isArchive!(ArchiveType), format!(`The type "`, ArchiveType, `" does not implement the necessary methods to be an archive.`)); | |
39 | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
40 alias ArchiveType.ErrorCallback ErrorCallback; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
41 alias ArchiveType.DataType DataType; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
42 |
0 | 43 private |
44 { | |
45 ArchiveType archive; | |
46 | |
47 RegisterBase[string] serializers; | |
48 RegisterBase[string] deserializers; | |
49 | |
50 size_t keyCounter; | |
51 | |
52 bool hasBegunSerializing; | |
53 bool hasBegunDeserializing; | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
54 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
55 void delegate (ArchiveException exception, DataType[] data) throwOnErrorCallback; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
56 void delegate (ArchiveException exception, DataType[] data) doNothingOnErrorCallback; |
0 | 57 } |
58 | |
59 this () | |
60 { | |
61 archive = new ArchiveType; | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
62 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
63 throwOnErrorCallback = (ArchiveException exception, DataType[] data) { throw exception; }; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
64 doNothingOnErrorCallback = (ArchiveException exception, DataType[] data) { /* do nothing */ }; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
65 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
66 setThrowOnErrorCallback(); |
0 | 67 } |
68 | |
69 void registerSerializer (T) (string type, void delegate (T, Serializer, DataType) dg) | |
70 { | |
71 serializers[type] = toSerializeRegisterWrapper(dg); | |
72 } | |
73 | |
74 void registerSerializer (T) (string type, void function (T, Serializer, DataType) func) | |
75 { | |
76 serializers[type] = toSerializeRegisterWrapper(func); | |
77 } | |
78 | |
79 void registerDeserializer (T) (string type, void delegate (ref T, Serializer, DataType) dg) | |
80 { | |
81 deserializers[type] = toDeserializeRegisterWrapper(dg); | |
82 } | |
83 | |
84 void registerDeserializer (T) (string type, void function (ref T, Serializer, DataType) func) | |
85 { | |
86 deserializers[type] = toDeserializeRegisterWrapper(func); | |
87 } | |
88 | |
89 void reset () | |
90 { | |
91 hasBegunSerializing = false; | |
92 hasBegunDeserializing = false; | |
93 resetCounters(); | |
94 | |
95 archive.reset; | |
96 } | |
97 | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
98 ErrorCallback errorCallback () |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
99 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
100 return archive.errorCallback; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
101 } |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
102 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
103 ErrorCallback errorCallback (ErrorCallback errorCallback) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
104 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
105 return archive.errorCallback = errorCallback; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
106 } |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
107 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
108 void setThrowOnErrorCallback () |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
109 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
110 errorCallback = throwOnErrorCallback; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
111 } |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
112 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
113 void setDoNothingOnErrorCallback () |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
114 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
115 errorCallback = doNothingOnErrorCallback; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
116 } |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
17
diff
changeset
|
117 |
0 | 118 DataType serialize (T) (T value, DataType key = null) |
119 { | |
120 if (!hasBegunSerializing) | |
121 hasBegunSerializing = true; | |
122 | |
123 if (!key) | |
124 key = nextKey; | |
125 | |
126 archive.beginArchiving(); | |
127 | |
128 static if (isTypeDef!(T)) | |
129 serializeTypeDef(value, key); | |
130 | |
131 static if (isObject!(T)) | |
132 serializeObject(value, key); | |
133 | |
134 else static if (isStruct!(T)) | |
135 serializeStruct(value, key); | |
136 | |
137 else static if (isString!(T)) | |
138 serializeString(value, key); | |
139 | |
140 else static if (isArray!(T)) | |
141 serializeArray(value, key); | |
142 | |
143 else static if (isAssociativeArray!(T)) | |
144 serializeAssociativeArray(value, key); | |
145 | |
146 else static if (isPrimitive!(T)) | |
147 serializePrimitive(value, key); | |
148 | |
149 else static if (isPointer!(T)) | |
150 { | |
151 static if (isFunctionPointer!(T)) | |
2 | 152 goto error; |
0 | 153 |
154 else | |
155 serializePointer(value, key); | |
2 | 156 } |
0 | 157 |
158 else static if (isEnum!(T)) | |
159 serializeEnum(value, key); | |
160 | |
161 else | |
2 | 162 { |
163 error: | |
164 throw new SerializationException(format!(`The type "`, T, `" cannot be serialized.`), __FILE__, __LINE__); | |
165 } | |
0 | 166 |
167 return archive.data; | |
168 } | |
169 | |
170 private void serializeObject (T) (T value, DataType key) | |
2 | 171 { |
0 | 172 triggerEvents(serializing, value, { |
173 archive.archive(value, key, { | |
174 auto runtimeType = value.classinfo.name; | |
175 | |
176 if (runtimeType in serializers) | |
177 { | |
178 auto wrapper = getSerializerWrapper!(T)(runtimeType); | |
179 wrapper(value, this, key); | |
180 } | |
181 | |
17
c4e7e64ffb67
Changed toData/fromData to take an instance of the serializer instead of the archive.
Jacob Carlborg <doob@me.com>
parents:
16
diff
changeset
|
182 else static if (isSerializable!(T, Serializer)) |
0 | 183 value.toData(this, key); |
184 | |
185 else | |
186 { | |
187 if (isBaseClass(value)) | |
188 throw new SerializationException(`The object of the static type "` ~ T.stringof ~ `" have a different runtime type (` ~ runtimeType ~ `) and therefore needs to register a serializer for its type "` ~ runtimeType ~ `".`, __FILE__, __LINE__); | |
189 | |
2 | 190 objectStructSerializeHelper(value); |
0 | 191 } |
192 }); | |
193 }); | |
194 } | |
195 | |
196 private void serializeStruct (T) (T value, DataType key) | |
197 { | |
198 triggerEvents(serializing, value, { | |
199 archive.archive(value, key, { | |
200 auto type = toDataType(T.stringof); | |
201 | |
202 if (type in serializers) | |
203 { | |
204 auto wrapper = getSerializerWrapper!(T)(type); | |
205 wrapper(value, this, key); | |
206 } | |
207 | |
208 else | |
209 { | |
17
c4e7e64ffb67
Changed toData/fromData to take an instance of the serializer instead of the archive.
Jacob Carlborg <doob@me.com>
parents:
16
diff
changeset
|
210 static if (isSerializable!(T, Serializer)) |
0 | 211 value.toData(this, key); |
212 | |
213 else | |
2 | 214 objectStructSerializeHelper(value); |
0 | 215 } |
216 }); | |
217 }); | |
218 } | |
219 | |
220 private void serializeString (T) (T value, DataType key) | |
221 { | |
222 archive.archive(value, key); | |
223 } | |
224 | |
225 private void serializeArray (T) (T value, DataType key) | |
226 { | |
227 archive.archive(value, key, { | |
228 foreach (i, e ; value) | |
14
6e454595b203
Fixed (de)serializing of arrays and associative arrays.
Jacob Carlborg <doob@me.com>
parents:
9
diff
changeset
|
229 serialize(e, toDataType(i)); |
0 | 230 }); |
231 } | |
232 | |
233 private void serializeAssociativeArray (T) (T value, DataType key) | |
234 { | |
235 archive.archive(value, key, { | |
236 foreach(k, v ; value) | |
14
6e454595b203
Fixed (de)serializing of arrays and associative arrays.
Jacob Carlborg <doob@me.com>
parents:
9
diff
changeset
|
237 serialize(v, toDataType(k)); |
0 | 238 }); |
239 } | |
240 | |
241 private void serializePointer (T) (T value, DataType key) | |
242 { | |
243 archive.archive(value, key, { | |
244 if (key in serializers) | |
245 { | |
246 auto wrapper = getSerializerWrapper!(T)(key); | |
247 wrapper(value, this, key); | |
248 } | |
249 | |
17
c4e7e64ffb67
Changed toData/fromData to take an instance of the serializer instead of the archive.
Jacob Carlborg <doob@me.com>
parents:
16
diff
changeset
|
250 else static if (isSerializable!(T, Serializer)) |
0 | 251 value.toData(this, key); |
252 | |
253 else | |
254 { | |
255 static if (isVoid!(BaseTypeOfPointer!(T))) | |
256 throw new SerializationException(`The value with the key "` ~ to!(string)(key) ~ `"` ~ format!(` of the type "`, T, `" cannot be serialized on its own, either implement orange.serialization.Serializable.isSerializable or register a serializer.`), __FILE__, __LINE__); | |
257 | |
258 else | |
259 serialize(*value, key); | |
260 } | |
261 }); | |
262 } | |
263 | |
264 private void serializeEnum (T) (T value, DataType key) | |
265 { | |
266 archive.archive(value, key); | |
267 } | |
268 | |
269 private void serializePrimitive (T) (T value, DataType key) | |
270 { | |
271 archive.archive(value, key); | |
272 } | |
273 | |
274 private void serializeTypeDef (T) (T value, DataType key) | |
275 { | |
276 archive.archive(value, key, { | |
277 serialize!(BaseTypeOfTypeDef!(T))(value, key); | |
278 }); | |
279 } | |
280 | |
281 T deserialize (T) (DataType data, DataType key = null) | |
282 { | |
283 if (hasBegunSerializing && !hasBegunDeserializing) | |
284 resetCounters(); | |
285 | |
286 if (!hasBegunDeserializing) | |
287 hasBegunDeserializing = true; | |
288 | |
289 if (!key) | |
290 key = nextKey; | |
291 | |
292 archive.beginUnarchiving(data); | |
293 return deserializeInternal!(T)(key); | |
294 } | |
295 | |
296 private T deserializeInternal (T) (DataType key) | |
297 { | |
298 static if (isTypeDef!(T)) | |
299 return deserializeTypeDef!(T)(key); | |
300 | |
301 else static if (isObject!(T)) | |
302 return deserializeObject!(T)(key); | |
303 | |
304 else static if (isStruct!(T)) | |
305 return deserializeStruct!(T)(key); | |
306 | |
307 else static if (isString!(T)) | |
308 return deserializeString!(T)(key); | |
309 | |
310 else static if (isArray!(T)) | |
311 return deserializeArray!(T)(key); | |
312 | |
313 else static if (isAssociativeArray!(T)) | |
314 return deserializeAssociativeArray!(T)(key); | |
315 | |
316 else static if (isPrimitive!(T)) | |
317 return deserializePrimitive!(T)(key); | |
318 | |
319 else static if (isPointer!(T)) | |
2 | 320 { |
321 static if (isFunctionPointer!(T)) | |
322 goto error; | |
323 | |
0 | 324 return deserializePointer!(T)(key); |
2 | 325 } |
0 | 326 |
327 else static if (isEnum!(T)) | |
328 return deserializeEnum!(T)(key); | |
329 | |
330 else | |
2 | 331 { |
332 error: | |
333 throw new SerializationException(format!(`The type "`, T, `" cannot be deserialized.`), __FILE__, __LINE__); | |
334 } | |
0 | 335 } |
336 | |
337 private T deserializeObject (T) (DataType key) | |
338 { | |
2 | 339 T value = archive.unarchive!(T)(key, (T value) { |
0 | 340 triggerEvents(deserializing, value, { |
341 auto runtimeType = value.classinfo.name; | |
342 | |
343 if (runtimeType in deserializers) | |
344 { | |
345 auto wrapper = getDeserializerWrapper!(T)(runtimeType); | |
346 wrapper(value, this, key); | |
347 } | |
348 | |
17
c4e7e64ffb67
Changed toData/fromData to take an instance of the serializer instead of the archive.
Jacob Carlborg <doob@me.com>
parents:
16
diff
changeset
|
349 else static if (isSerializable!(T, Serializer)) |
0 | 350 value.fromData(this, key); |
351 | |
352 else | |
353 { | |
354 if (isBaseClass(value)) | |
355 throw new SerializationException(`The object of the static type "` ~ T.stringof ~ `" have a different runtime type (` ~ runtimeType ~ `) and therefore needs to register a deserializer for its type "` ~ runtimeType ~ `".`, __FILE__, __LINE__); | |
356 | |
2 | 357 objectStructDeserializeHelper(value); |
0 | 358 } |
359 }); | |
360 | |
361 return value; | |
362 }); | |
363 | |
364 return value; | |
365 } | |
366 | |
367 private T deserializeStruct (T) (DataType key) | |
368 { | |
369 return archive.unarchive!(T)(key, (T value) { | |
370 triggerEvents(deserializing, value, { | |
371 auto type = toDataType(T.stringof); | |
372 | |
373 if (type in deserializers) | |
374 { | |
375 auto wrapper = getDeserializerWrapper!(T)(type); | |
376 wrapper(value, this, key); | |
377 } | |
378 | |
379 else | |
380 { | |
17
c4e7e64ffb67
Changed toData/fromData to take an instance of the serializer instead of the archive.
Jacob Carlborg <doob@me.com>
parents:
16
diff
changeset
|
381 static if (isSerializable!(T, Serializer)) |
0 | 382 value.fromData(this, key); |
383 | |
384 else | |
2 | 385 objectStructDeserializeHelper(value); |
0 | 386 } |
387 }); | |
388 | |
389 return value; | |
390 }); | |
391 } | |
392 | |
393 private T deserializeString (T) (DataType key) | |
394 { | |
395 return archive.unarchive!(T)(key); | |
396 } | |
397 | |
398 private T deserializeArray (T) (DataType key) | |
399 { | |
400 return archive.unarchive!(T)(key, (T value) { | |
401 foreach (i, ref e ; value) | |
14
6e454595b203
Fixed (de)serializing of arrays and associative arrays.
Jacob Carlborg <doob@me.com>
parents:
9
diff
changeset
|
402 e = deserializeInternal!(typeof(e))(toDataType(i)); |
0 | 403 |
404 return value; | |
405 }); | |
406 } | |
407 | |
408 private T deserializeAssociativeArray (T) (DataType key) | |
409 { | |
410 return archive.unarchive!(T)(key, (T value) { | |
411 foreach (k, v ; archive.unarchiveAssociativeArrayVisitor!(T)) | |
412 value[k] = v; | |
413 | |
414 return value; | |
415 }); | |
416 } | |
417 | |
418 private T deserializePointer (T) (DataType key) | |
419 { | |
420 return archive.unarchive!(T)(key, (T value) { | |
421 if (key in deserializers) | |
422 { | |
423 auto wrapper = getDeserializerWrapper!(T)(key); | |
424 wrapper(value, this, key); | |
425 } | |
426 | |
17
c4e7e64ffb67
Changed toData/fromData to take an instance of the serializer instead of the archive.
Jacob Carlborg <doob@me.com>
parents:
16
diff
changeset
|
427 else static if (isSerializable!(T, Serializer)) |
0 | 428 value.fromData(this, key); |
429 | |
430 else | |
431 { | |
432 static if (isVoid!(BaseTypeOfPointer!(T))) | |
433 throw new SerializationException(`The value with the key "` ~ to!(string)(key) ~ `"` ~ format!(` of the type "`, T, `" cannot be deserialized on its own, either implement orange.serialization.Serializable.isSerializable or register a deserializer.`), __FILE__, __LINE__); | |
434 | |
435 else | |
436 *value = deserializeInternal!(BaseTypeOfPointer!(T))(key); | |
437 } | |
438 | |
439 return value; | |
440 }); | |
441 } | |
442 | |
443 private T deserializeEnum (T) (DataType key) | |
444 { | |
445 return archive.unarchive!(T)(key); | |
446 } | |
447 | |
448 private T deserializePrimitive (T) (DataType key) | |
449 { | |
450 return archive.unarchive!(T)(key); | |
451 } | |
452 | |
453 private T deserializeTypeDef (T) (DataType key) | |
454 { | |
455 return archive.unarchive!(T)(key, (T value) { | |
456 return deserializeInternal!(BaseTypeOfTypeDef!(T))(key); | |
457 }); | |
458 } | |
459 | |
3 | 460 private void objectStructSerializeHelper (T) (ref T value) |
461 { | |
462 static assert(isStruct!(T) || isObject!(T), format!(`The given value of the type "`, T, `" is not a valid type, the only valid types for this method are objects and structs.`)); | |
8 | 463 const nonSerializedFields = collectAnnotations!(nonSerializedField, T); |
3 | 464 |
465 foreach (i, dummy ; typeof(T.tupleof)) | |
466 { | |
467 const field = nameOfFieldAt!(T, i); | |
468 | |
469 static if (!internalFields.ctfeContains(field) && !nonSerializedFields.ctfeContains(field)) | |
470 { | |
471 alias typeof(T.tupleof[i]) Type; | |
472 Type v = value.tupleof[i]; | |
473 serialize(v, toDataType(field)); | |
474 } | |
475 } | |
2 | 476 |
4
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
477 static if (isObject!(T) && !is(T == Object)) |
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
478 serializeBaseTypes(value); |
3 | 479 } |
480 | |
481 private void objectStructDeserializeHelper (T) (ref T value) | |
482 { | |
483 static assert(isStruct!(T) || isObject!(T), format!(`The given value of the type "`, T, `" is not a valid type, the only valid types for this method are objects and structs.`)); | |
8 | 484 const nonSerializedFields = collectAnnotations!(nonSerializedField, T); |
3 | 485 |
486 foreach (i, dummy ; typeof(T.tupleof)) | |
487 { | |
488 const field = nameOfFieldAt!(T, i); | |
489 | |
490 static if (!internalFields.ctfeContains(field) && !nonSerializedFields.ctfeContains(field)) | |
491 { | |
492 alias TypeOfField!(T, field) Type; | |
493 auto fieldValue = deserializeInternal!(Type)(toDataType(field)); | |
494 value.tupleof[i] = fieldValue; | |
495 } | |
496 } | |
4
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
497 |
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
498 static if (isObject!(T) && !is(T == Object)) |
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
499 deserializeBaseTypes(value); |
0 | 500 } |
501 | |
2 | 502 private void serializeBaseTypes (T : Object) (T value) |
0 | 503 { |
504 alias BaseTypeTupleOf!(T)[0] Base; | |
505 | |
506 static if (!is(Base == Object)) | |
507 { | |
508 archive.archiveBaseClass!(Base)(nextKey); | |
4
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
509 Base base = value; |
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
510 objectStructSerializeHelper(base); |
0 | 511 } |
512 } | |
513 | |
2 | 514 private void deserializeBaseTypes (T : Object) (T value) |
0 | 515 { |
516 alias BaseTypeTupleOf!(T)[0] Base; | |
517 | |
518 static if (!is(Base == Object)) | |
519 { | |
520 archive.unarchiveBaseClass!(Base)(nextKey); | |
4
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
521 Base base = value; |
470ab5270d0c
Simplified the implementation of RegisterWrapper. Fixed: the base class of an object was not serialized
Jacob Carlborg <doob@me.com>
parents:
3
diff
changeset
|
522 objectStructDeserializeHelper(base); |
0 | 523 } |
524 } | |
525 | |
15
9f6064f9505a
Changed from archive to serializer in the register wrappers.
Jacob Carlborg <doob@me.com>
parents:
14
diff
changeset
|
526 private SerializeRegisterWrapper!(T, Serializer) getSerializerWrapper (T) (string type) |
0 | 527 { |
15
9f6064f9505a
Changed from archive to serializer in the register wrappers.
Jacob Carlborg <doob@me.com>
parents:
14
diff
changeset
|
528 auto wrapper = cast(SerializeRegisterWrapper!(T, Serializer)) serializers[type]; |
0 | 529 |
530 if (wrapper) | |
531 return wrapper; | |
532 | |
533 assert(false, "throw exception here"); | |
534 } | |
535 | |
15
9f6064f9505a
Changed from archive to serializer in the register wrappers.
Jacob Carlborg <doob@me.com>
parents:
14
diff
changeset
|
536 private DeserializeRegisterWrapper!(T, Serializer) getDeserializerWrapper (T) (string type) |
0 | 537 { |
15
9f6064f9505a
Changed from archive to serializer in the register wrappers.
Jacob Carlborg <doob@me.com>
parents:
14
diff
changeset
|
538 auto wrapper = cast(DeserializeRegisterWrapper!(T, Serializer)) deserializers[type]; |
0 | 539 |
540 if (wrapper) | |
541 return wrapper; | |
542 | |
543 assert(false, "throw exception here"); | |
544 } | |
545 | |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
546 private SerializeRegisterWrapper!(T, Serializer) toSerializeRegisterWrapper (T) (void delegate (T, Serializer, DataType) dg) |
0 | 547 { |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
548 return new SerializeRegisterWrapper!(T, Serializer)(dg); |
0 | 549 } |
550 | |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
551 private SerializeRegisterWrapper!(T, Serializer) toSerializeRegisterWrapper (T) (void function (T, Serializer, DataType) func) |
0 | 552 { |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
553 return new SerializeRegisterWrapper!(T, Serializer)(func); |
0 | 554 } |
555 | |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
556 private DeserializeRegisterWrapper!(T, Serializer) toDeserializeRegisterWrapper (T) (void delegate (ref T, Serializer, DataType) dg) |
0 | 557 { |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
558 return new DeserializeRegisterWrapper!(T, Serializer)(dg); |
0 | 559 } |
560 | |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
561 private DeserializeRegisterWrapper!(T, Serializer) toDeserializeRegisterWrapper (T) (void function (ref T, Serializer, DataType) func) |
0 | 562 { |
16
091ff1b263db
Missed some in the previous commit.
Jacob Carlborg <doob@me.com>
parents:
15
diff
changeset
|
563 return new DeserializeRegisterWrapper!(T, Serializer)(func); |
0 | 564 } |
565 | |
566 private DataType toDataType (T) (T value) | |
567 { | |
568 try | |
569 return to!(DataType)(value); | |
570 | |
571 catch (ConversionException e) | |
572 throw new SerializationException(e); | |
573 } | |
574 | |
575 private bool isBaseClass (T) (T value) | |
576 { | |
577 auto name = value.classinfo.name; | |
578 auto index = name.lastIndexOf('.'); | |
579 | |
580 return T.stringof != name[index + 1 .. $]; | |
581 } | |
582 | |
583 private DataType nextKey () | |
584 { | |
585 return toDataType(keyCounter++); | |
586 } | |
587 | |
588 private void resetCounters () | |
589 { | |
590 keyCounter = 0; | |
591 } | |
592 | |
593 private void triggerEvent (string name, T) (T value) | |
594 { | |
3 | 595 static assert (isObject!(T) || isStruct!(T), format!(`The given value of the type "`, T, `" is not a valid type, the only valid types for this method are objects and structs.`)); |
0 | 596 |
597 foreach (i, dummy ; typeof(T.tupleof)) | |
598 { | |
599 const field = nameOfFieldAt!(T, i); | |
600 | |
601 static if (field == name) | |
602 { | |
603 alias TypeOfField!(T, field) Type; | |
604 auto event = getValueOfField!(T, Type, field)(value); | |
605 event(value); | |
606 } | |
607 } | |
608 } | |
609 | |
610 private void triggerEvents (T) (Mode mode, T value, void delegate () dg) | |
611 { | |
612 if (mode == serializing) | |
613 triggerEvent!(onSerializingField)(value); | |
614 | |
615 else | |
616 triggerEvent!(onDeserializingField)(value); | |
617 | |
618 dg(); | |
619 | |
620 if (mode == serializing) | |
621 triggerEvent!(onSerializedField)(value); | |
622 | |
623 else | |
624 triggerEvent!(onDeserializedField)(value); | |
625 } | |
626 | |
8 | 627 private static string[] collectAnnotations (string name, T) () |
0 | 628 { |
3 | 629 static assert (isObject!(T) || isStruct!(T), format!(`The given value of the type "`, T, `" is not a valid type, the only valid types for this method are objects and structs.`)); |
0 | 630 |
631 string[] annotations; | |
632 | |
8 | 633 foreach (i, type ; typeof(T.tupleof)) |
0 | 634 { |
635 const field = nameOfFieldAt!(T, i); | |
636 | |
637 static if (field == name) | |
8 | 638 annotations ~= type.field; |
0 | 639 } |
640 | |
641 return annotations; | |
642 } | |
643 } |