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