1 /**
2  * Copyright: Copyright (c) 2010-2011 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 import std.conv;
10 import std.array;
11 
12 import orange.core.Attribute;
13 import orange.serialization._;
14 import orange.serialization.archives.Archive;
15 import orange.util._;
16 import orange.util.collection.Array;
17 
18 private
19 {
20     alias orange.util.CTFE.contains ctfeContains;
21 
22     enum Mode
23     {
24         serializing,
25         deserializing
26     }
27 
28     alias Mode.serializing serializing;
29     alias Mode.deserializing deserializing;
30 
31     private char toUpper () (char c)
32     {
33         if (c >= 'a' && c <= 'z')
34             return cast(char) (c - 32);
35 
36         return c;
37     }
38 }
39 
40 /**
41  * This class represents a serializer. It's the main interface to the (de)serialization
42  * process and it's this class that actually performs most of the (de)serialization.
43  *
44  * The serializer is the frontend in the serialization process, it's independent of the
45  * underlying archive type. It's responsible for collecting and tracking all values that
46  * should be (de)serialized. It's the serializer that adds keys and ID's to all values,
47  * keeps track of references to make sure that a given value (of reference type) is only
48  * (de)serialized once.
49  *
50  * The serializer is also responsible for breaking up types that the underlying archive
51  * cannot handle, into primitive types that archive know how to (de)serialize.
52  *
53  * Keys are used by the serializer to associate a name with a value. It's used to
54  * deserialize values independently of the order of the fields of a class or struct.
55  * They can also be used by the user to give a name to a value. Keys are unique within
56  * it's scope.
57  *
58  * ID's are an unique identifier associated with each serialized value. The serializer
59  * uses the ID's to track values when (de)serializing reference types. An ID is unique
60  * across the whole serialized data.
61  *
62  * Examples:
63  * ---
64  * import std.stdio;
65  * import orange.serialization._;
66  * import orange.serialization.archives._;
67  *
68  * class Foo
69  * {
70  *     int a;
71  * }
72  *
73  * void main ()
74  * {
75  *     auto archive = new XmlArchive!();
76  *     auto serializer = new Serializer;
77  *
78  *     auto foo = new Foo;
79  *     foo.a = 3;
80  *
81  *     serializer.serialize(foo);
82  *     auto foo2 = serializer.deserialize!(Foo)(archive.untypedData);
83  *
84  *     writeln(foo2.a); // prints "3"
85  *     assert(foo.a == foo2.a);
86  * }
87  * ---
88  */
89 class Serializer
90 {
91     /// The type of error callback.
92     alias Archive.ErrorCallback ErrorCallback;
93 
94     /// The type of the serialized data. This is an untyped format.
95     alias Archive.UntypedData Data;
96 
97     /// The type of an ID.
98     alias Archive.Id Id;
99 
100     /**
101      * This callback will be called when an unexpected event occurs, i.e. an expected element
102      * is missing in the deserialization process.
103      *
104      * Examples:
105      * ---
106      * auto archive = new XmlArchive!();
107      * auto serializer = new Serializer(archive);
108      * serializer.errorCallback = (SerializationException exception) {
109      *     writeln(exception);
110      *     throw exception;
111      * };
112      * ---
113      */
114     ErrorCallback errorCallback ()
115     {
116         return archive.errorCallback;
117     }
118 
119     /**
120      * This callback will be called when an unexpected event occurs, i.e. an expected element
121      * is missing in the deserialization process.
122      *
123      * Examples:
124      * ---
125      * auto archive = new XmlArchive!();
126      * auto serializer = new Serializer(archive);
127      * serializer.errorCallback = (SerializationException exception) {
128      *     writeln(exception);
129      *     throw exception;
130      * };
131      * ---
132      */
133     ErrorCallback errorCallback (ErrorCallback errorCallback)
134     {
135         return archive.errorCallback = errorCallback;
136     }
137 
138     private
139     {
140         struct ValueMeta
141         {
142             Id id = Id.max;
143             string key;
144 
145             bool isValid ()
146             {
147                 return id != Id.max && key.length > 0;
148             }
149         }
150 
151         static
152         {
153             void function (Serializer serializer, in Object, Mode mode) [ClassInfo] registeredTypes;
154             RegisterBase[string] serializers;
155             RegisterBase[string] deserializers;
156         }
157 
158         Archive archive_;
159 
160         size_t keyCounter;
161         Id idCounter;
162 
163         RegisterBase[string] overriddenSerializers;
164         RegisterBase[string] overriddenDeserializers;
165 
166         Id[void*] serializedReferences;
167         void*[Id] deserializedReferences;
168 
169         Array[Id] serializedArrays;
170         void[][Id] deserializedSlices;
171 
172         void**[Id] deserializedPointers;
173 
174         ValueMeta[void*] serializedValues;
175 
176         const(void)*[Id] deserializedValues;
177 
178         bool hasBegunSerializing;
179         bool hasBegunDeserializing;
180 
181         void delegate (SerializationException exception) throwOnErrorCallback;
182         void delegate (SerializationException exception) doNothingOnErrorCallback;
183 
184         Mode mode;
185     }
186 
187     /**
188      * Creates a new serializer using the given archive.
189      *
190      * The archive is the backend of the (de)serialization process, it performs the low
191      * level (de)serialization of primitive values and it decides the final format of the
192      * serialized data.
193      *
194      * Params:
195      *     archive = the archive that should be used for this serializer
196      *
197      * Examples:
198      * ---
199      * auto archive = new XmlArchive!();
200      * auto serializer = new Serializer(archive);
201      * ---
202      */
203     this (Archive archive)
204     {
205         this.archive_ = archive;
206 
207         throwOnErrorCallback = (SerializationException exception) { throw exception; };
208         doNothingOnErrorCallback = (SerializationException exception) { /* do nothing */ };
209 
210         setThrowOnErrorCallback();
211     }
212 
213     /**
214      * Registers the given type for (de)serialization.
215      *
216      * This method is used for register classes that will be (de)serialized through base
217      * class references, no other types need to be registered. If the the user tries to
218      * (de)serialize an instance through a base class reference which runtime type is not
219      * registered an exception will be thrown.
220      *
221      * Params:
222      *     T = the type to register, must be a class
223      *
224      * Examples:
225      * ---
226      * class Base {}
227      * class Sub : Base {}
228      *
229      * Serializer.register!(Sub);
230      *
231      * auto archive = new XmlArchive!();
232      * auto serializer = new Serializer(archive);
233      *
234      * Base b = new Sub;
235      * serializer.serialize(b);
236      * ---
237      *
238      * See_Also: registerSerializer
239      * See_Also: registerDeserializer
240      */
241     static void register (T : Object) ()
242     {
243         registeredTypes[T.classinfo] = &downcastSerialize!(T);
244     }
245 
246     private static void downcastSerialize (U : Object) (Serializer serializer, in Object value, Mode mode)
247     {
248         alias Unqual!(U) T;
249 
250         static if (!isNonSerialized!(T)())
251         {
252             auto casted = cast(T) value;
253             assert(casted);
254             assert(casted.classinfo is T.classinfo);
255 
256             if (mode == serializing)
257                 serializer.objectStructSerializeHelper(casted);
258 
259             else
260                 serializer.objectStructDeserializeHelper(casted);
261         }
262     }
263 
264     /**
265      * Registers a serializer for the given type.
266      *
267      * The given callback will be called when a value of the given type is about to
268      * be serialized. This method can be used as an alternative to $(I register). This
269      * method can also be used as an alternative to Serializable.toData.
270      *
271      * This is method should also be used to perform custom serialization of third party
272      * types or when otherwise chaining an already existing type is not desired.
273      *
274      * Params:
275      *     dg = the callback that will be called when value of the given type is about to be serialized
276      *
277      * Examples:
278      * ---
279      * class Base {}
280      * class Foo : Base {}
281      *
282      * auto archive = new XmlArchive!();
283      * auto serializer = new Serializer(archive);
284      *
285      * auto dg = (Base value, Serializer serializer, Data key) {
286      *     // perform serialization
287      * };
288      *
289      * Serializer.registerSerializer!(Foo)(dg);
290      * ---
291      *
292      * See_Also: register
293      * See_Also: registerDeserializer
294      * See_Also: Serializable.toData
295      */
296     static void registerSerializer (Derived, Base) (void delegate (Base, Serializer, Data) dg) if (is(T == class) || is(T == interface))
297     {
298         Serializer.serializers[typeid(Derived).toString] = toSerializeRegisterWrapper(dg);
299     }
300 
301     /// ditto
302     static void registerSerializer (T) (void delegate (ref T, Serializer, Data) dg) if (is(T == struct))
303     {
304         Serializer.serializers[typeid(T).toString] = toSerializeRegisterWrapper(dg);
305     }
306 
307     /// ditto
308     static void registerSerializer (T) (void delegate (T, Serializer, Data) dg)
309     {
310         Serializer.serializers[typeid(T).toString] = toSerializeRegisterWrapper(dg);
311     }
312 
313     /**
314      * Registers a serializer for the given type.
315      *
316      * The given callback will be called when a value of the given type is about to
317      * be serialized. This method can be used as an alternative to $(I register). This
318      * method can also be used as an alternative to Serializable.toData.
319      *
320      * This is method should also be used to perform custom serialization of third party
321      * types or when otherwise chaining an already existing type is not desired.
322      *
323      * Params:
324      *     func = the callback that will be called when value of the given type is about to be serialized
325      *
326      * Examples:
327      * ---
328      * class Base {}
329      * class Foo : Base {}
330      *
331      * auto archive = new XmlArchive!();
332      * auto serializer = new Serializer(archive);
333      *
334      * void func (Base value, Serializer serializer, Data key) {
335      *     // perform serialization
336      * }
337      *
338      * Serializer.registerSerializer!(Foo)(&func);
339      * ---
340      *
341      * See_Also: register
342      * See_Also: registerDeserializer
343      * See_Also: Serializable.toData
344      */
345     static void registerSerializer (Derived, Base) (void function (Base, Serializer, Data) func) if (is(T == class) || is(T == interface))
346     {
347         Serializer.serializers[typeid(Derived).toString] = toSerializeRegisterWrapper(func);
348     }
349 
350     /// ditto
351     static void registerSerializer (T) (void function (ref T, Serializer, Data) func) if (is(T == struct))
352     {
353         Serializer.serializers[typeid(T).toString] = toSerializeRegisterWrapper(func);
354     }
355 
356     /// ditto
357     static void registerSerializer (T) (void function (T, Serializer, Data) func)
358     {
359         Serializer.serializers[typeid(T).toString] = toSerializeRegisterWrapper(func);
360     }
361 
362     /**
363      * Registers a deserializer for the given type.
364      *
365      * The given callback will be called when a value of the given type is about to
366      * be deserialized. This method can be used as an alternative to $(I register). This
367      * method can also be used as an alternative to Serializable.fromData.
368      *
369      * This is method should also be used to perform custom deserialization of third party
370      * types or when otherwise chaining an already existing type is not desired.
371      *
372      * Params:
373      *     dg = the callback that will be called when value of the given type is about to be deserialized
374      *
375      * Examples:
376      * ---
377      * class Base {}
378      * class Foo : Base {}
379      *
380      * auto archive = new XmlArchive!();
381      * auto serializer = new Serializer(archive);
382      *
383      * auto dg = (ref Base value, Serializer serializer, Data key) {
384      *     // perform deserialization
385      * };
386      *
387      * Serializer.registerDeserializer!(Foo)(dg);
388      * ---
389      *
390      * See_Also: register
391      * See_Also: registerSerializer
392      * See_Also: Serializable.fromData
393      */
394     static void registerDeserializer (Derived, Base) (void delegate (ref Base, Serializer, Data) dg) if (is(T == class) || is(T == interface))
395     {
396         Serializer.deserializers[typeid(Derived).toString] = toDeserializeRegisterWrapper(dg);
397     }
398 
399     /// ditto
400     static void registerDeserializer (T) (void delegate (ref T, Serializer, Data) dg)
401     {
402         Serializer.deserializers[typeid(T).toString] = toDeserializeRegisterWrapper(dg);
403     }
404 
405     /**
406      * Registers a deserializer for the given type.
407      *
408      * The given callback will be called when a value of the given type is about to
409      * be deserialized. This method can be used as an alternative to $(I register). This
410      * method can also be used as an alternative to Serializable.fromData.
411      *
412      * This is method should also be used to perform custom deserialization of third party
413      * types or when otherwise chaining an already existing type is not desired.
414      *
415      * Params:
416      *     func = the callback that will be called when value of the given type is about to be deserialized
417      *
418      * Examples:
419      * ---
420      * class Base {}
421      * class Foo : Base {}
422      *
423      * auto archive = new XmlArchive!();
424      * auto serializer = new Serializer(archive);
425      *
426      * void func (ref Base value, Serializer serializer, Data key) {
427      *     // perform deserialization
428      * }
429      *
430      * Serializer.registerDeserializer!(Foo)(&func);
431      * ---
432      *
433      * See_Also: register
434      * See_Also: registerSerializer
435      * See_Also: Serializable.fromData
436      */
437     static void registerDeserializer (Derived, Base) (void function (ref Base, Serializer, Data) func) if (is(T == class) || is(T == interface))
438     {
439         Serializer.deserializers[typeid(Derived).toString] = toDeserializeRegisterWrapper(func);
440     }
441 
442     /// ditto
443     static void registerDeserializer (T) (void function (ref T, Serializer, Data) func)
444     {
445         Serializer.deserializers[typeid(T).toString] = toDeserializeRegisterWrapper(func);
446     }
447 
448     /**
449      * Overrides a globally registered serializer for the given type with a serializer
450      * local to the receiver.
451      *
452      * The receiver will first check if a local serializer is registered, otherwise a global
453      * serializer will be used (if available).
454      *
455      * Params:
456      *     dg = the callback that will be called when value of the given type is about to be serialized
457      *
458      * Examples:
459      * ---
460      * class Base {}
461      * class Foo : Base {}
462      *
463      * auto archive = new XmlArchive!();
464      * auto serializer = new Serializer(archive);
465      *
466      * auto dg = (Base value, Serializer serializer, Data key) {
467      *     // perform serialization
468      * };
469      *
470      * Serializer.registerSerializer!(Foo)(dg);
471      *
472      * auto overrideDg = (Base value, Serializer serializer, Data key) {
473      *     // this will override the above serializer
474      * }
475      *
476      * serializer.overrideSerializer!(Foo)(overrideDg);
477      * ---
478      */
479     void overrideSerializer (Derived, Base) (void delegate (Base, Serializer, Data) dg) if (is(T == class) || is(T == interface))
480     {
481         overriddenSerializers[typeid(Derived).toString] = toSerializeRegisterWrapper(dg);
482     }
483 
484     /// ditto
485     void overrideSerializer (T) (void delegate (ref T, Serializer, Data) dg) if (is(T == struct))
486     {
487         overriddenSerializers[typeid(T).toString] = toSerializeRegisterWrapper(dg);
488     }
489 
490     /// ditto
491     void overrideSerializer (T) (void delegate (T, Serializer, Data) dg)
492     {
493         overriddenSerializers[typeid(T).toString] = toSerializeRegisterWrapper(dg);
494     }
495 
496     /**
497      * Overrides a globally registered serializer for the given type with a serializer
498      * local to the receiver.
499      *
500      * The receiver will first check if a local serializer is registered, otherwise a global
501      * serializer will be used (if available).
502      *
503      * Params:
504      *     func = the callback that will be called when value of the given type is about to be serialized
505      *
506      * Examples:
507      * ---
508      * class Base {}
509      * class Foo : Base {}
510      *
511      * auto archive = new XmlArchive!();
512      * auto serializer = new Serializer(archive);
513      *
514      * void func (Base value, Serializer serializer, Data key) {
515      *     // perform serialization
516      * }
517      *
518      * Serializer.registerSerializer!(Foo)(&func);
519      *
520      * void overrideFunc (Base value, Serializer serializer, Data key) {
521      *     // this will override the above serializer
522      * }
523      *
524      * serializer.overrideSerializer!(Foo)(&overrideFunc);
525      * ---
526      */
527     void overrideSerializer (Derived, Base) (void function (Base, Serializer, Data) func) if (is(T == class) || is(T == interface))
528     {
529         overriddenSerializers[typeid(Derived).toString] = toSerializeRegisterWrapper(func);
530     }
531 
532     /// ditto
533     void overrideSerializer (T) (void function (ref T, Serializer, Data) func) if (is(T == struct))
534     {
535         overriddenSerializers[typeid(T).toString] = toSerializeRegisterWrapper(func);
536     }
537 
538     /// ditto
539     void overrideSerializer (T) (void function (T, Serializer, Data) func)
540     {
541         overriddenSerializers[typeid(T).toString] = toSerializeRegisterWrapper(func);
542     }
543 
544     /**
545      * Overrides a globally registered deserializer for the given type with a deserializer
546      * local to the receiver.
547      *
548      * The receiver will first check if a local deserializer is registered, otherwise a global
549      * deserializer will be used (if available).
550      *
551      * Params:
552      *     dg = the callback that will be called when value of the given type is about to be deserialized
553      *
554      * Examples:
555      * ---
556      * class Base {}
557      * class Foo : Base {}
558      *
559      * auto archive = new XmlArchive!();
560      * auto serializer = new Serializer(archive);
561      *
562      * auto dg = (ref Base value, Serializer serializer, Data key) {
563      *     // perform deserialization
564      * };
565      *
566      * Serializer.registerSerializer!(Foo)(dg);
567      *
568      * auto overrideDg = (ref Base value, Serializer serializer, Data key) {
569      *     // this will override the above deserializer
570      * };
571      *
572      * serializer.overrideSerializer!(Foo)(overrideDg);
573      * ---
574      */
575     void overrideDeserializer (Derived, Base) (void delegate (ref Base, Serializer, Data) dg) if (is(T == class) || is(T == interface))
576     {
577         overriddenDeserializers[typeid(Derived).toString] = toDeserializeRegisterWrapper(dg);
578     }
579 
580     /// ditto
581     void overrideDeserializer (T) (void delegate (ref T, Serializer, Data) dg)
582     {
583         overriddenDeserializers[typeid(T).toString] = toDeserializeRegisterWrapper(dg);
584     }
585 
586     /**
587      * Overrides a globally registered deserializer for the given type with a deserializer
588      * local to the receiver.
589      *
590      * The receiver will first check if a local deserializer is registered, otherwise a global
591      * deserializer will be used (if available).
592      *
593      * Params:
594      *     func = the callback that will be called when value of the given type is about to be deserialized
595      *
596      * Examples:
597      * ---
598      * class Base {}
599      * class Foo : Base {}
600      *
601      * auto archive = new XmlArchive!();
602      * auto serializer = new Serializer(archive);
603      *
604      * void func (ref Base value, Serializer serializer, Data key) {
605      *     // perform deserialization
606      * }
607      *
608      * Serializer.registerSerializer!(Foo)(&func);
609      *
610      * void overrideFunc (ref Base value, Serializer serializer, Data key) {
611      *     // this will override the above deserializer
612      * }
613      *
614      * serializer.overrideSerializer!(Foo)(&overrideFunc);
615      * ---
616      */
617     void overrideDeserializer (Derived, Base) (void function (ref Base, Serializer, Data) func) if (is(T == class) || is(T == interface))
618     {
619         overriddenDeserializers[typeid(Derived).toString] = toDeserializeRegisterWrapper(func);
620     }
621 
622     /// ditto
623     void overrideDeserializer (T) (void function (ref T, Serializer, Data) func)
624     {
625         overriddenDeserializers[typeid(T).toString] = toDeserializeRegisterWrapper(func);
626     }
627 
628     /// Returns the receivers archive
629     Archive archive ()
630     {
631         return archive_;
632     }
633 
634     /**
635      * Set the error callback to throw when an error occurs
636      *
637      * See_Also: setDoNothingOnErrorCallback
638      */
639     void setThrowOnErrorCallback ()
640     {
641         errorCallback = throwOnErrorCallback;
642     }
643 
644     /**
645      * Set the error callback do nothing when an error occurs
646      *
647      * See_Also: setThrowOnErrorCallback
648      */
649     void setDoNothingOnErrorCallback ()
650     {
651         errorCallback = doNothingOnErrorCallback;
652     }
653 
654     /**
655      * Resets all registered types registered via the "register" method
656      *
657      * See_Also: register
658      */
659     static void resetRegisteredTypes ()
660     {
661         registeredTypes = null;
662     }
663 
664     /**
665      * Resets all registered (de)serializers registered via the "registerSerializer" method.
666      * This method will not reset the overridden (de)serializers.
667      *
668      * See_Also: registerSerializer
669      * See_Also: registerDeserializer
670      */
671     static void resetSerializers ()
672     {
673         serializers = null;
674         deserializers = null;
675     }
676 
677     /**
678      * Resets the serializer.
679      *
680      * All internal data is reset, including the archive. After calling this method the
681      * serializer can be used to start a completely new (de)serialization process.
682      */
683     void reset ()
684     {
685         resetCounters();
686 
687         overriddenSerializers = null;
688         overriddenDeserializers = null;
689 
690         serializedReferences = null;
691         deserializedReferences = null;
692 
693         serializedArrays = null;
694         deserializedSlices = null;
695 
696         serializedValues = null;
697         deserializedValues = null;
698 
699         deserializedPointers = null;
700 
701         hasBegunSerializing = false;
702         hasBegunDeserializing = false;
703 
704         archive.reset;
705 
706         mode = Mode.init;
707     }
708 
709     /**
710      * Serializes the given value.
711      *
712      * Params:
713      *     value = the value to serialize
714      *     key = associates the value with the given key. This key can later be used to
715      *              deserialize the value
716      *
717       * Examples:
718      * ---
719      * auto archive = new XmlArchive!();
720      * auto serializer = new Serializer(archive);
721      *
722      * serializer.serialize(1);
723      * serializer.serialize(2, "b");
724      * ---
725      *
726      * Returns: return the serialized data, in an untyped format.
727      *
728      * Throws: SerializationException if an error occurs
729      */
730     Data serialize (T) (auto ref T value, string key = null)
731     {
732         mode = serializing;
733 
734         if (!hasBegunSerializing)
735             hasBegunSerializing = true;
736 
737         serializeInternal(value, key);
738         postProcess;
739 
740         return archive.untypedData;
741     }
742 
743     /**
744      * Serializes the base class(es) of an instance.
745      *
746      * This method is used when performing custom serialization of a given type. If this
747      * method is not called when performing custom serialization none of the instance's
748      * base classes will be serialized.
749      *
750      * Params:
751      *     value = the instance which base class(es) should be serialized, usually $(D_CODE this)
752      *
753      * Examples:
754      * ---
755      * class Base {}
756      * class Sub : Base
757      * {
758      *     void toData (Serializer serializer, Serializer.Data key)
759      *     {
760      *         // perform serialization
761      *         serializer.serializeBase(this);
762      *     }
763      * }
764      * ---
765      *
766      * Throws: SerializationException if an error occurs
767      */
768     void serializeBase (T) (T value)
769     {
770         static if (isObject!(T) && !is(Unqual!(T) == Object))
771                 serializeBaseTypes(value);
772     }
773 
774     private void serializeInternal (U) (ref U value, string key = null, Id id = Id.max)
775     {
776         alias Unqual!(U) T;
777 
778         if (!key)
779             key = nextKey;
780 
781         if (id == Id.max)
782             id = nextId;
783 
784         archive.beginArchiving();
785 
786         static if (isObject!(T))
787             serializeObject(value, key, id);
788 
789         else static if (isStruct!(T))
790             serializeStruct(value, key, id);
791 
792         else static if (isString!(T))
793             serializeString(value, key, id);
794 
795         else static if (isArray!(T))
796             serializeArray(value, key, id);
797 
798         else static if (isAssociativeArray!(T))
799             serializeAssociativeArray(value, key, id);
800 
801         else static if (isPrimitive!(T))
802             serializePrimitive(value, key, id);
803 
804         else static if (isPointer!(T))
805         {
806             static if (isFunctionPointer!(T))
807                 goto error;
808 
809             else
810                 serializePointer(value, key, id);
811         }
812 
813         else static if (isEnum!(T))
814             serializeEnum(value, key, id);
815 
816         else
817         {
818             error:
819             error(format!(`The type "`, T, `" cannot be serialized.`));
820         }
821     }
822 
823     private void serializeObject (T) (T value, string key, Id id) if (isObject!(T))
824     {
825         auto typeName = typeid(T).toString;
826 
827         static if (!isNonSerialized!(T)())
828         {
829             if (!value)
830                 return archive.archiveNull(typeName, key);
831 
832             auto reference = getSerializedReference(value);
833 
834             if (reference != Id.max)
835                 return archive.archiveReference(key, reference);
836 
837             auto untypedValue = cast(Object) value;
838             auto runtimeType = untypedValue.classinfo.name;
839 
840             addSerializedReference(value, id);
841 
842             triggerEvents(value, {
843                 archive.archiveObject(runtimeType, typeName, key, id, {
844                     if (auto serializer = runtimeType in overriddenSerializers)
845                         callSerializer(serializer, value, key);
846 
847                     else if (auto serializer = runtimeType in Serializer.serializers)
848                         callSerializer(serializer, value, key);
849 
850                     else static if (isSerializable!(T))
851                         value.toData(this, key);
852 
853                     else
854                     {
855                         if (isInterface!(T) || isBaseClass(value))
856                         {
857                             if (auto serializer = untypedValue.classinfo in registeredTypes)
858                                 (*serializer)(this, untypedValue, serializing);
859 
860                             else
861                                 error(`The object of the static type "` ~ typeName ~
862                                     `" have a different runtime type (` ~ runtimeType ~
863                                     `) and therefore needs to either register its type or register a serializer for its type "`
864                                     ~ runtimeType ~ `".`);
865                         }
866 
867                         else
868                             objectStructSerializeHelper(value);
869                     }
870                 });
871             });
872         }
873     }
874 
875     private void serializeStruct (T) (ref T value, string key, Id id)
876     {
877         static if (!isNonSerialized!(T)())
878         {
879             string type = typeid(T).toString;
880 
881             triggerEvents(value, {
882                 archive.archiveStruct(type, key, id, {
883                     if (auto serializer = type in overriddenSerializers)
884                         callSerializer(serializer, value, key);
885 
886                     else if (auto serializer = type in Serializer.serializers)
887                         callSerializer(serializer, value, key);
888 
889                     else
890                     {
891                         static if (isSerializable!(T))
892                             value.toData(this, key);
893 
894                         else
895                             objectStructSerializeHelper(value);
896                     }
897                 });
898             });
899         }
900     }
901 
902     private void serializeString (T) (T value, string key, Id id)
903     {
904         auto array = Array(cast(void*) value.ptr, value.length, ElementTypeOfArray!(T).sizeof);
905 
906         archive.archive(value, key, id);
907 
908         if (value.length > 0)
909             addSerializedArray(array, id);
910     }
911 
912     private void serializeArray (T) (ref T value, string key, Id id)
913     {
914         auto array = Array(value.ptr, value.length, ElementTypeOfArray!(T).sizeof);
915 
916         archive.archiveArray(array, arrayToString!(T), key, id, {
917             for (size_t i = 0; i < value.length; i++)
918             {
919                 const e = value[i];
920                 serializeInternal(e, toData(i));
921             }
922         });
923 
924         if (value.length > 0)
925             addSerializedArray(array, id);
926     }
927 
928     private void serializeAssociativeArray (T) (T value, string key, Id id)
929     {
930         auto reference = getSerializedReference(value);
931 
932         if (reference != Id.max)
933             return archive.archiveReference(key, reference);
934 
935         addSerializedReference(value, id);
936 
937         string keyType = typeid(KeyTypeOfAssociativeArray!(T)).toString;
938         string valueType = typeid(ValueTypeOfAssociativeArray!(T)).toString;
939 
940         archive.archiveAssociativeArray(keyType, valueType, value.length, key, id, {
941             size_t i;
942 
943             foreach(k, v ; value)
944             {
945                 archive.archiveAssociativeArrayKey(toData(i), {
946                     serializeInternal(k, toData(i));
947                 });
948 
949                 archive.archiveAssociativeArrayValue(toData(i), {
950                     serializeInternal(v, toData(i));
951                 });
952 
953                 i++;
954             }
955         });
956     }
957 
958     private void serializePointer (T) (T value, string key, Id id)
959     {
960         if (!value)
961             return archive.archiveNull(typeid(T).toString, key);
962 
963         auto reference = getSerializedReference(value);
964 
965         if (reference != Id.max)
966             return archive.archiveReference(key, reference);
967 
968         archive.archivePointer(key, id, {
969             if (auto serializer = key in overriddenSerializers)
970                 callSerializer(serializer, value, key);
971 
972             else if (auto serializer = key in Serializer.serializers)
973                 callSerializer(serializer, value, key);
974 
975             else static if (isSerializable!(T))
976                 value.toData(this, key);
977 
978             else
979             {
980                 static if (isVoid!(BaseTypeOfPointer!(T)))
981                     error(`The value with the key "` ~ to!(string)(key) ~ `"` ~
982                         format!(` of the type "`, T, `" cannot be serialized on `,
983                         `its own, either implement orange.serialization.Serializable`,
984                         `.isSerializable or register a serializer.`));
985 
986                 else
987                 {
988                     auto valueMeta = getSerializedValue(value);
989 
990                     if (valueMeta.isValid)
991                         archive.archiveReference(nextKey, valueMeta.id);
992 
993                     else
994                         serializeInternal(*value, nextKey);
995                 }
996             }
997         });
998 
999         addSerializedReference(value, id);
1000     }
1001 
1002     private void serializeEnum (T) (T value, string key, Id id)
1003     {
1004         alias BaseTypeOfEnum!(T) EnumBaseType;
1005         auto val = cast(EnumBaseType) value;
1006         string type = typeid(T).toString;
1007 
1008         archive.archiveEnum(val, type, key, id);
1009     }
1010 
1011     private void serializePrimitive (T) (T value, string key, Id id)
1012     {
1013         archive.archive(value, key, id);
1014     }
1015 
1016     /**
1017      * Deserializes the given data to value of the given type.
1018      *
1019      * This is the main method used for deserializing data.
1020      *
1021      * Examples:
1022      * ---
1023      * auto archive = new XmlArchive!();
1024      * auto serializer = new Serializer(archive);
1025      *
1026      * auto data = serializer.serialize(1);
1027      * auto i = serializer.deserialize!(int)(data);
1028      *
1029      * assert(i == 1);
1030      * ---
1031      *
1032      * Params:
1033      *        T = the type to deserialize the data into
1034      *     data = the serialized untyped data to deserialize
1035      *     key = the key associate with the value that was used during serialization.
1036      *              Do not specify a key if no key was used during serialization.
1037      *
1038      * Returns: the deserialized value. A different runtime type can be returned
1039      *             if the given type is a base class.
1040      *
1041      * Throws: SerializationException if an error occurs
1042      */
1043     T deserialize (T) (Data data, string key = "")
1044     {
1045         mode = deserializing;
1046 
1047         if (hasBegunSerializing && !hasBegunDeserializing)
1048             resetCounters();
1049 
1050         if (!hasBegunDeserializing)
1051             hasBegunDeserializing = true;
1052 
1053         if (key.empty())
1054             key = nextKey;
1055 
1056         archive.beginUnarchiving(data);
1057         auto value = deserializeInternal!(T)(key);
1058         deserializingPostProcess;
1059 
1060         return value;
1061     }
1062 
1063     /**
1064      * Deserializes the value with the given associated key.
1065      *
1066      * This method should only be called when performing custom an deserializing a value
1067      * that is part of an class or struct. If this method is called before that actual
1068      * deserialization process has begun an SerializationException will be thrown.
1069      * Use this method if a key was specified during the serialization process.
1070      *
1071      * Examples:
1072      * ---
1073      * class Foo
1074      * {
1075      *     int a;
1076      *
1077      *     void fromData (Serializer serializer, Serializer.Data key)
1078      *     {
1079      *         a = serializer!(int)("a");
1080      *     }
1081      * }
1082      * ---
1083      *
1084      * Params:
1085      *     key = the key associate with the value that was used during serialization.
1086      *
1087      * Returns: the deserialized value. A different runtime type can be returned
1088      *             if the given type is a base class.
1089      *
1090      * Throws: SerializationException if this method is called before
1091      *            the actual deserialization process has begun.
1092      *
1093      * Throws: SerializationException if an error occurs
1094      */
1095     T deserialize (T) (string key)
1096     {
1097         if (!hasBegunDeserializing)
1098             error("Cannot deserialize without any data, this method should" ~
1099                 "only be called after deserialization has begun.");
1100 
1101         return deserialize!(T)(archive.untypedData, key);
1102     }
1103 
1104     /**
1105      * Deserializes the value with the given associated key.
1106      *
1107      * This method should only be called when performing custom an deserializing a value
1108      * that is part of an class or struct. If this method is called before that actual
1109      * deserialization process has begun an SerializationException will be thrown.
1110      * Use this method if no key was specified during the serialization process.
1111      *
1112      * Examples:
1113      * ---
1114      * class Foo
1115      * {
1116      *     int a;
1117      *
1118      *     void fromData (Serializer serializer, Serializer.Data key)
1119      *     {
1120      *         a = serializer!(int)();
1121      *     }
1122      * }
1123      * ---
1124      *
1125      * Returns: the deserialized value. A different runtime type can be returned
1126      *             if the given type is a base class.
1127      *
1128      * Throws: SerializationException if this method is called before
1129      *            the actual deserialization process has begun.
1130      *
1131      * Throws: SerializationException if an error occurs
1132      */
1133     T deserialize (T) ()
1134     {
1135         return deserialize!(T)("");
1136     }
1137 
1138     /**
1139      * Deserializes the base class(es) of an instance.
1140      *
1141      * This method is used when performing custom deserialization of a given type. If this
1142      * method is not called when performing custom deserialization none of the instance's
1143      * base classes will be serialized.
1144      *
1145      * Params:
1146      *     value = the instance which base class(es) should be deserialized,
1147      *                usually $(D_CODE this)
1148      *
1149      * Examples:
1150      * ---
1151      * class Base {}
1152      * class Sub : Base
1153      * {
1154      *     void fromData (Serializer serializer, Serializer.Data key)
1155      *     {
1156      *         // perform deserialization
1157      *         serializer.deserializeBase(this);
1158      *     }
1159      * }
1160      * ---
1161      *
1162      * Throws: SerializationException if an error occurs
1163      */
1164     void deserializeBase (T) (T value)
1165     {
1166         static if (isObject!(T) && !is(Unqual!(T) == Object))
1167             deserializeBaseTypes(value);
1168     }
1169 
1170     private Unqual!(U) deserializeInternal (U, Key) (Key keyOrId)
1171     {
1172         Id dummy;
1173         return deserializeInternal!(U, Key)(keyOrId, dummy);
1174     }
1175 
1176     private Unqual!(U) deserializeInternal (U, Key) (Key keyOrId, out Id id)
1177     {
1178         alias Unqual!(U) T;
1179 
1180         static if (isObject!(T))
1181             return deserializeObject!(T)(keyOrId, id);
1182 
1183         else static if (isStruct!(T))
1184             return deserializeStruct!(T)(keyOrId, id);
1185 
1186         else static if (isString!(T))
1187             return deserializeString!(T)(keyOrId, id);
1188 
1189         else static if (isStaticArray!(T))
1190             return deserializeStaticArray!(T)(keyOrId, id);
1191 
1192         else static if (isArray!(T))
1193             return deserializeArray!(T)(keyOrId, id);
1194 
1195         else static if (isAssociativeArray!(T))
1196             return deserializeAssociativeArray!(T)(keyOrId, id);
1197 
1198         else static if (isPrimitive!(T))
1199             return deserializePrimitive!(T)(keyOrId, id);
1200 
1201         else static if (isPointer!(T))
1202         {
1203             static if (isFunctionPointer!(T))
1204                 goto error;
1205 
1206             return deserializePointer!(T)(keyOrId, id).value;
1207         }
1208 
1209         else static if (isEnum!(T))
1210             return deserializeEnum!(T)(keyOrId, id);
1211 
1212         else
1213         {
1214             error:
1215             error(format!(`The type "`, T, `" cannot be deserialized.`));
1216         }
1217     }
1218 
1219     private Unqual!(U) deserializeObject (U, Key) (Key keyOrId, out Id id)
1220     {
1221         alias Unqual!(U) T;
1222 
1223         static if (!isNonSerialized!(T)())
1224         {
1225             id = deserializeReference(keyOrId);
1226 
1227             if (auto reference = getDeserializedReference!(T)(id))
1228                 return *reference;
1229 
1230             T value;
1231             Object untypedValue;
1232             nextId;
1233 
1234             archive.unarchiveObject(keyOrId, id, untypedValue, {
1235                 value = cast(T) untypedValue;
1236                 addDeserializedReference(value, id);
1237                 assert(untypedValue !is null, format!("Failed to unarchive object of type '", T, "' with key '") ~ to!(string)(keyOrId) ~ "'");
1238 
1239                 triggerEvents(value, {
1240                     auto runtimeType = untypedValue.classinfo.name;
1241                     auto runHelper = false;
1242 
1243                     static if (isString!(Key))
1244                     {
1245                         if (auto deserializer = runtimeType in overriddenDeserializers)
1246                             callSerializer(deserializer, value, keyOrId);
1247 
1248                         else if (auto deserializer = runtimeType in Serializer.deserializers)
1249                             callSerializer(deserializer, value, keyOrId);
1250 
1251                         else static if (isSerializable!(T))
1252                             value.fromData(this, keyOrId);
1253 
1254                         else
1255                             runHelper = true;
1256                     }
1257 
1258                     else
1259                         runHelper = true;
1260 
1261                     if (runHelper)
1262                     {
1263                         if (isInterface!(T) || isBaseClass(value))
1264                         {
1265                             if (auto deserializer = untypedValue.classinfo in registeredTypes)
1266                                 (*deserializer)(this, untypedValue, deserializing);
1267 
1268                             else
1269                                 error(`The object of the static type "` ~ typeid(T).toString ~
1270                                     `" have a different runtime type (` ~ runtimeType ~
1271                                     `) and therefore needs to either register its type or register a deserializer for its type "`
1272                                     ~ runtimeType ~ `".`);
1273                         }
1274 
1275                         else
1276                             objectStructDeserializeHelper(value);
1277                     }
1278                 });
1279             });
1280 
1281             return value;
1282         }
1283         else
1284         {
1285             return T.init;
1286         }
1287     }
1288 
1289     private T deserializeStruct (T, U) (U key, out Id id)
1290     {
1291         T value;
1292 
1293         static if (!isNonSerialized!(T)())
1294         {
1295             nextId;
1296 
1297             id = archive.unarchiveStruct(key, {
1298                 triggerEvents(value, {
1299                     auto type = toData(typeid(T).toString);
1300                     auto runHelper = false;
1301 
1302                     static if (isString!(U))
1303                     {
1304                         if (auto deserializer = type in overriddenDeserializers)
1305                             callSerializer(deserializer, value, key);
1306 
1307                         else if (auto deserializer = type in Serializer.deserializers)
1308                             callSerializer(deserializer, value, key);
1309 
1310                         else
1311                             runHelper = true;
1312                     }
1313 
1314                     else
1315                         runHelper = true;
1316 
1317                     if (runHelper)
1318                     {
1319                         static if (isSerializable!(T))
1320                             value.fromData(this, key);
1321 
1322                         else
1323                             objectStructDeserializeHelper(value);
1324                     }
1325                 });
1326             });
1327         }
1328 
1329         return value;
1330     }
1331 
1332     private T deserializeString (T) (string key, out Id id)
1333     {
1334         auto slice = deserializeSlice(key);
1335 
1336         if (auto tmp = getDeserializedSlice!(T)(slice))
1337             return tmp;
1338 
1339         T value;
1340 
1341         if (slice.id != size_t.max)
1342         {
1343             static if (is(T == string))
1344                 value = toSlice(archive.unarchiveString(slice.id), slice);
1345 
1346             else static if (is(T == wstring))
1347                 value = toSlice(archive.unarchiveWstring(slice.id), slice);
1348 
1349             else static if (is(T == dstring))
1350                 value = toSlice(archive.unarchiveDstring(slice.id), slice);
1351         }
1352 
1353         else
1354         {
1355             static if (is(T == string))
1356                 value = archive.unarchiveString(key, slice.id);
1357 
1358             else static if (is(T == wstring))
1359                 value = archive.unarchiveWstring(key, slice.id);
1360 
1361             else static if (is(T == dstring))
1362                 value = archive.unarchiveDstring(key, slice.id);
1363         }
1364 
1365         addDeserializedSlice(value, slice.id);
1366 
1367         id = slice.id;
1368         return value;
1369     }
1370 
1371     private T deserializeArray (T) (string key, out Id id)
1372     {
1373         auto slice = deserializeSlice(key);
1374 
1375         if (auto tmp = getDeserializedSlice!(T)(slice))
1376             return tmp;
1377 
1378         alias ElementTypeOfArray!(T) E;
1379         alias Unqual!(E) UnqualfiedE;
1380 
1381         UnqualfiedE[] buffer;
1382         T value;
1383 
1384         auto dg = (size_t length) {
1385             buffer.length = length;
1386 
1387             foreach (i, ref e ; buffer)
1388                 e = deserializeInternal!(typeof(e))(toData(i));
1389         };
1390 
1391         if (slice.id != size_t.max) // Deserialize slice
1392         {
1393             id = slice.id;
1394             archive.unarchiveArray(slice.id, dg);
1395             assumeUnique(buffer, value);
1396             addDeserializedSlice(value, slice.id);
1397 
1398             return toSlice(value, slice);
1399         }
1400 
1401         else // Deserialize array
1402         {
1403             id = archive.unarchiveArray(key, dg);
1404 
1405             if (auto arr = id in deserializedSlices)
1406                 return cast(T) *arr;
1407 
1408             assumeUnique(buffer, value);
1409             addDeserializedSlice(value, id);
1410 
1411             return value;
1412         }
1413     }
1414 
1415     private T deserializeStaticArray (T) (string key, out Id id)
1416     {
1417         T value;
1418 
1419         id = archive.unarchiveArray(key, (size_t length) {
1420             foreach (i, ref e ; value)
1421                 e = deserializeInternal!(typeof(e))(toData(i));
1422         });
1423 
1424         return value;
1425     }
1426 
1427     private T deserializeAssociativeArray (T) (string key, out Id id)
1428     {
1429         id = deserializeReference(key);
1430 
1431         if (auto reference = getDeserializedReference!(T)(id))
1432             return *reference;
1433 
1434         alias KeyTypeOfAssociativeArray!(T) Key;
1435         alias ValueTypeOfAssociativeArray!(T) Value;
1436 
1437         alias Unqual!(Key) UKey;
1438         alias Unqual!(Value) UValue;
1439 
1440         UValue[UKey] buffer;
1441 
1442         id = archive.unarchiveAssociativeArray(key, (size_t length) {
1443             for (size_t i = 0; i < length; i++)
1444             {
1445                 UKey aaKey;
1446                 UValue aaValue;
1447                 auto k = toData(i);
1448 
1449                 archive.unarchiveAssociativeArrayKey(k, {
1450                     aaKey = deserializeInternal!(Key)(k);
1451                 });
1452 
1453                 archive.unarchiveAssociativeArrayValue(k, {
1454                     aaValue = deserializeInternal!(Value)(k);
1455                 });
1456 
1457                 buffer[aaKey] = aaValue;
1458             }
1459         });
1460 
1461         T value = buffer;
1462         addDeserializedReference(value, id);
1463 
1464         return value;
1465     }
1466 
1467     private Pointer!(T) deserializePointer (T) (string key)
1468     {
1469         auto pointeeId = deserializeReference(key);
1470 
1471         if (auto reference = getDeserializedReference!(T)(pointeeId))
1472             return Pointer!(T)(*reference, Id.max);
1473 
1474         alias BaseTypeOfPointer!(T) BaseType;
1475         alias Unqual!(BaseType) UnqualfiedBaseType;
1476 
1477         auto pointer = new UnqualfiedBaseType;
1478 
1479         auto pointerId = archive.unarchivePointer(key, {
1480             if (auto deserializer = key in overriddenDeserializers)
1481                 callSerializer(deserializer, pointer, key);
1482 
1483             else if (auto deserializer = key in Serializer.deserializers)
1484                 callSerializer(deserializer, pointer, key);
1485 
1486             else static if (isSerializable!(T))
1487                 pointer.fromData(this, key);
1488 
1489             else
1490             {
1491                 static if (isVoid!(BaseTypeOfPointer!(T)))
1492                     error(`The value with the key "` ~ to!(string)(key) ~ `"` ~
1493                         format!(` of the type "`, T, `" cannot be ` ~
1494                         "deserialized on its own, either implement " ~
1495                         "orange.serialization.Serializable.isSerializable or " ~
1496                         "register a deserializer."));
1497 
1498                 else
1499                 {
1500                     auto k = nextKey;
1501                     pointeeId = deserializeReference(k);
1502 
1503                     if (pointeeId == Id.max)
1504                         *pointer = deserializeInternal!(UnqualfiedBaseType)(k);
1505                 }
1506             }
1507         });
1508 
1509         if (pointeeId != Id.max)
1510             *pointer = deserializeInternal!(UnqualfiedBaseType)(pointeeId);
1511 
1512         addDeserializedReference(pointer, pointerId);
1513 
1514         return Pointer!(T)(cast(T) pointer, pointerId, pointeeId);
1515     }
1516 
1517     private T deserializeEnum (T, U) (U keyOrId, out Id id)
1518     {
1519         alias BaseTypeOfEnum!(T) Enum;
1520 
1521         enum functionName = toUpper(Enum.stringof[0]) ~ Enum.stringof[1 .. $];
1522 
1523         static if (is(U == Id))
1524             enum params = "(keyOrId);";
1525         else
1526             enum params = "(keyOrId, id);";
1527 
1528         mixin("return cast(T) archive.unarchiveEnum" ~ functionName ~ params);
1529     }
1530 
1531     private T deserializePrimitive (T, U) (U keyOrId, out Id id)
1532     {
1533         enum functionName = toUpper(T.stringof[0]) ~ T.stringof[1 .. $];
1534 
1535         static if (is(U == Id))
1536             enum params = "(keyOrId);";
1537         else
1538             enum params = "(keyOrId, id);";
1539 
1540         mixin("return archive.unarchive" ~ functionName ~ params);
1541     }
1542 
1543     private Id deserializeReference (string key)
1544     {
1545         return archive.unarchiveReference(key);
1546     }
1547 
1548     private Slice deserializeSlice (string key)
1549     {
1550         return archive.unarchiveSlice(key);
1551     }
1552 
1553     private void objectStructSerializeHelper (T) (ref T value)
1554     {
1555         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.`));
1556 
1557         enum nonSerializedFields = collectAnnotations!(T);
1558 
1559         foreach (i, _ ; typeof(T.tupleof))
1560         {
1561             enum field = nameOfFieldAt!(T, i);
1562             alias attributes = getAttributes!(T.tupleof[i]);
1563 
1564             static if (attributes.contains!(nonSerialized) ||
1565                 ctfeContains!(string)(internalFields, field) ||
1566                 ctfeContains!(string)(nonSerializedFields, field))
1567             {
1568                 continue;
1569             }
1570             else
1571             {
1572 
1573                 alias typeof(T.tupleof[i]) Type;
1574 
1575                 auto id = nextId;
1576 
1577                 static if (isPointer!(Type))
1578                     auto pointer = value.tupleof[i];
1579 
1580                 else
1581                     auto pointer = &value.tupleof[i];
1582 
1583                 auto reference = getSerializedReference(value.tupleof[i]);
1584 
1585                 if (reference != Id.max)
1586                     archive.archiveReference(field, reference);
1587 
1588                 else
1589                 {
1590                     auto valueMeta = getSerializedValue(pointer);
1591 
1592                     if (valueMeta.isValid)
1593                         serializePointer(pointer, toData(field), id);
1594 
1595                     else
1596                     {
1597                         serializeInternal(value.tupleof[i], toData(field), id);
1598                         addSerializedValue(pointer, id, toData(keyCounter));
1599                     }
1600                 }
1601             }
1602         }
1603 
1604         static if (isObject!(T) && !is(Unqual!(T) == Object))
1605             serializeBaseTypes(value);
1606     }
1607 
1608     private void objectStructDeserializeHelper (T) (ref T value)
1609     {
1610         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.`));
1611 
1612         enum nonSerializedFields = collectAnnotations!(T);
1613 
1614         static if (isObject!(T))
1615             auto rawObject = cast(void*) value;
1616 
1617         else
1618             auto rawObject = cast(void*) &value;
1619 
1620         foreach (i, _ ; typeof(T.tupleof))
1621         {
1622             enum field = nameOfFieldAt!(T, i);
1623             alias attributes = getAttributes!(T.tupleof[i]);
1624 
1625             static if (attributes.contains!(nonSerialized) ||
1626                 ctfeContains!(string)(internalFields, field) ||
1627                 ctfeContains!(string)(nonSerializedFields, field))
1628             {
1629                 continue;
1630             }
1631             else
1632             {
1633 
1634                 alias TypeOfField!(T, field) QualifiedType;
1635                 alias Unqual!(QualifiedType) Type;
1636 
1637                 auto id = deserializeReference(field);
1638                 auto isReference = id != Id.max;
1639                 auto offset = value.tupleof[i].offsetof;
1640                 auto fieldAddress = cast(Type*) (rawObject + offset);
1641 
1642                 static if (isPointer!(Type))
1643                 {
1644                     auto pointer = deserializePointer!(Type)(toData(field));
1645                     Type pointerValue;
1646 
1647                     if (pointer.hasPointee)
1648                         pointerValue = getDeserializedValue!(Type)(pointer.pointee);
1649 
1650                     else
1651                         pointerValue = pointer.value;
1652 
1653                     *fieldAddress = pointerValue;
1654                     addDeserializedPointer(value.tupleof[i], pointer.id);
1655                 }
1656 
1657                 else
1658                 {
1659                     auto pointer = getDeserializedPointer!(Type*)(id);
1660 
1661                     if (isReference && pointer)
1662                     {
1663                         *fieldAddress = **pointer;
1664                         *pointer = cast(Type*) &value.tupleof[i];
1665                     }
1666 
1667                     else
1668                     {
1669                         *fieldAddress = deserializeInternal!(Type)(toData(field), id);
1670                         addDeserializedValue(value.tupleof[i], id);
1671 
1672                         static if (isStaticArray!(Type))
1673                             addDeserializedSlice(value.tupleof[i], id);
1674                     }
1675                 }
1676             }
1677         }
1678 
1679         static if (isObject!(T) && !is(Unqual!(T) == Object))
1680             deserializeBaseTypes(value);
1681     }
1682 
1683     private void serializeBaseTypes (T) (inout T value) if (isObject!(T))
1684     {
1685         static if (hasNonObjectBaseType!(T))
1686         {
1687             alias Base = BaseTypeTupleOf!(T)[0];
1688             archive.archiveBaseClass(typeid(Base).toString, nextKey, nextId);
1689             inout Base base = value;
1690             objectStructSerializeHelper(base);
1691         }
1692     }
1693 
1694     private void deserializeBaseTypes (T) (T value) if (isObject!(T))
1695     {
1696         static if (hasNonObjectBaseType!(T))
1697         {
1698             alias Base = BaseTypeTupleOf!(T)[0];
1699             archive.unarchiveBaseClass(nextKey);
1700             Base base = value;
1701             objectStructDeserializeHelper(base);
1702         }
1703     }
1704 
1705     private void addSerializedReference (T) (T value, Id id)
1706     {
1707         alias Unqual!(T) Type;
1708         static assert(isReference!(Type) || isAssociativeArray!(Type), format!(`The given type "`, T, `" is not a reference type, i.e. object, pointer or associative array.`));
1709 
1710         serializedReferences[cast(void*) value] = id;
1711     }
1712 
1713     private void addDeserializedReference (T) (T value, Id id)
1714     {
1715         static assert(isReference!(T) || isAssociativeArray!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object, pointer or associative array.`));
1716 
1717         deserializedReferences[id] = cast(void*) value;
1718     }
1719 
1720     private void addDeserializedSlice (T) (ref T value, Id id)
1721     {
1722         static assert(isArray!(T) || isString!(T), format!(`The given type "`, T, `" is not a slice type, i.e. array or string.`));
1723 
1724         deserializedSlices[id] = cast(void[]) value;
1725     }
1726 
1727     private void addSerializedValue (T) (T* value, Id id, string key)
1728     {
1729         serializedValues[value] = ValueMeta(id, key);
1730     }
1731 
1732     private void addDeserializedValue (T) (ref T value, Id id)
1733     {
1734         deserializedValues[id] = &value;
1735     }
1736 
1737     private void addDeserializedPointer (T) (ref T value, Id id)
1738     {
1739         deserializedPointers[id] = cast(void**) &value;
1740     }
1741 
1742     private Id getSerializedReference (T) (T value)
1743     {
1744         if (auto tmp = *(cast(void**) &value) in serializedReferences)
1745             return *tmp;
1746 
1747         return Id.max;
1748     }
1749 
1750     private ValueMeta getSerializedValue (T) (T* value)
1751     {
1752         if (auto tmp = value in serializedValues)
1753             return *tmp;
1754 
1755         return ValueMeta();
1756     }
1757 
1758     private T* getDeserializedReference (T) (Id id)
1759     {
1760         if (auto reference = id in deserializedReferences)
1761             return cast(T*) reference;
1762 
1763         return null;
1764     }
1765 
1766     private T getDeserializedSlice (T) (Slice slice)
1767     {
1768         if (auto array = slice.id in deserializedSlices)
1769         {
1770             auto typed = cast(T) *array;
1771             return typed[slice.offset .. slice.offset + slice.length];
1772         }
1773 
1774         return null;
1775     }
1776 
1777     private T getDeserializedValue (T) (Id id)
1778     {
1779         if (auto value = id in deserializedValues)
1780             return cast(T) *value;
1781 
1782         return null;
1783     }
1784 
1785     private T* getDeserializedPointer (T) (Id id)
1786     {
1787         if (auto pointer = id in deserializedPointers)
1788             return cast(T*) *pointer;
1789 
1790         return null;
1791     }
1792 
1793     private T[] toSlice (T) (T[] array, Slice slice)
1794     {
1795         return array[slice.offset .. slice.offset + slice.length];
1796     }
1797 
1798     void callSerializer (T) (RegisterBase* baseWrapper, ref T value, string key)
1799     {
1800         static if (is(T == struct))
1801             alias SerializeWrapper = SerializeRegisterWrapperRef!T;
1802 
1803         else
1804             alias SerializeWrapper = SerializeRegisterWrapper!T;
1805 
1806         if (mode == serializing)
1807         {
1808             auto wrapper = cast(SerializeWrapper) *baseWrapper;
1809             wrapper(value, this, key);
1810         }
1811 
1812         else
1813         {
1814             auto wrapper = cast(DeserializeRegisterWrapper!(T)) *baseWrapper;
1815             wrapper(value, this, key);
1816         }
1817     }
1818 
1819     static private SerializeRegisterWrapper!(T) toSerializeRegisterWrapper (T) (void delegate (T, Serializer, Data) dg)
1820     {
1821         return new SerializeRegisterWrapper!(T)(dg);
1822     }
1823 
1824     static private SerializeRegisterWrapperRef!(T) toSerializeRegisterWrapper (T) (void delegate (T, Serializer, Data) dg) if (is(T == struct))
1825     {
1826         return new SerializeRegisterWrapperRef!(T)(dg);
1827     }
1828 
1829     static private SerializeRegisterWrapper!(T) toSerializeRegisterWrapper (T) (void function (T, Serializer, Data) func)
1830     {
1831         return new SerializeRegisterWrapper!(T)(func);
1832     }
1833 
1834     static private SerializeRegisterWrapperRef!(T) toSerializeRegisterWrapper (T) (void function (ref T, Serializer, Data) func) if (is(T == struct))
1835     {
1836         return new SerializeRegisterWrapperRef!(T)(func);
1837     }
1838 
1839     static private DeserializeRegisterWrapper!(T) toDeserializeRegisterWrapper (T) (void delegate (ref T, Serializer, Data) dg)
1840     {
1841         return new DeserializeRegisterWrapper!(T)(dg);
1842     }
1843 
1844     static private DeserializeRegisterWrapper!(T) toDeserializeRegisterWrapper (T) (void function (ref T, Serializer, Data) func)
1845     {
1846         return new DeserializeRegisterWrapper!(T)(func);
1847     }
1848 
1849     private void addSerializedArray (Array array, Id id)
1850     {
1851         serializedArrays[id] = array;
1852     }
1853 
1854     private void postProcess ()
1855     {
1856         postProcessArrays();
1857     }
1858 
1859     private void postProcessArrays ()
1860     {
1861         bool foundSlice = true;
1862 
1863         foreach (sliceKey, slice ; serializedArrays)
1864         {
1865             foreach (arrayKey, array ; serializedArrays)
1866             {
1867                 if (slice.isSliceOf(array) && slice != array)
1868                 {
1869                     auto s = Slice(slice.length, (slice.ptr - array.ptr) / slice.elementSize);
1870                     archive.archiveSlice(s, sliceKey, arrayKey);
1871                     foundSlice = true;
1872                     break;
1873                 }
1874 
1875                 else
1876                     foundSlice = false;
1877             }
1878 
1879             if (!foundSlice)
1880                 archive.postProcessArray(sliceKey);
1881         }
1882     }
1883 
1884     private void deserializingPostProcess ()
1885     {
1886         deserializingPostProcessPointers;
1887     }
1888 
1889     private void deserializingPostProcessPointers ()
1890     {
1891         // foreach (pointeeId, pointee ; deserializedValues)
1892         // {
1893         //     if (auto pointer = pointeeId in deserializedPointers)
1894         //         **pointer = pointee;
1895         // }
1896     }
1897 
1898     private string arrayToString (T) ()
1899     {
1900         return typeid(ElementTypeOfArray!(T)).toString;
1901     }
1902 
1903     private bool isBaseClass (T) (T value)
1904     {
1905         return value.classinfo !is T.classinfo;
1906     }
1907 
1908     private Id nextId ()
1909     {
1910         return idCounter++;
1911     }
1912 
1913     private string nextKey ()
1914     {
1915         return toData(keyCounter++);
1916     }
1917 
1918     private void resetCounters ()
1919     {
1920         keyCounter = 0;
1921         idCounter = 0;
1922     }
1923 
1924     private string toData (T) (T value)
1925     {
1926         return to!(string)(value);
1927     }
1928 
1929     private void triggerEvent (string name, T) (ref T value)
1930     {
1931         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.`));
1932 
1933         static if (hasAnnotation!(T, name))
1934             __traits(getMember, T, name)(value);
1935     }
1936 
1937     private void triggertUdaEvent (alias event, T) (ref T value)
1938     {
1939         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.`));
1940 
1941         foreach (m ; __traits(allMembers, T))
1942         {
1943             static if (m != nonSerializedField)
1944             {
1945                 alias attrs = Attributes!(m, __traits(getAttributes, __traits(getMember, T, m)));
1946 
1947                 static if (attrs.contains!(event))
1948                     __traits(getMember, value, m)();
1949             }
1950         }
1951     }
1952 
1953     private void triggerEvents (T) (ref T value, void delegate () dg)
1954     {
1955         if (mode == serializing)
1956         {
1957             triggerEvent!(onSerializingField)(value);
1958             triggertUdaEvent!(onSerializing)(value);
1959         }
1960 
1961         else
1962         {
1963             triggerEvent!(onDeserializingField)(value);
1964             triggertUdaEvent!(onDeserializing)(value);
1965         }
1966 
1967         dg();
1968 
1969         if (mode == serializing)
1970         {
1971             triggerEvent!(onSerializedField)(value);
1972             triggertUdaEvent!(onSerialized)(value);
1973         }
1974 
1975         else
1976         {
1977             triggerEvent!(onDeserializedField)(value);
1978             triggertUdaEvent!(onDeserialized)(value);
1979         }
1980     }
1981 
1982     private static bool isNonSerialized (T) ()
1983     {
1984         enum nonSerializedFields = collectAnnotations!(T);
1985 
1986         return ctfeContains(nonSerializedFields, "this") || getAttributes!(T).contains!(nonSerialized);
1987     }
1988 
1989     private static template hasAnnotation (T, string annotation)
1990     {
1991         enum hasAnnotation = is(typeof({ mixin("const a = T." ~ annotation ~ ";"); }));
1992     }
1993 
1994     private static string[] collectAnnotations (T) ()
1995     {
1996         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.`));
1997 
1998         static if (hasAnnotation!(T, nonSerializedField))
1999             return T.__nonSerialized;
2000 
2001         else
2002             return [];
2003     }
2004 
2005     private void error (string message, size_t line = __LINE__)
2006     {
2007         if (errorCallback)
2008             errorCallback()(new SerializationException(message, __FILE__, line));
2009     }
2010 
2011     struct Pointer (T)
2012     {
2013         T value;
2014         Id id = Id.max;
2015         Id pointee = Id.max;
2016 
2017         bool hasPointee ()
2018         {
2019             return pointee != Id.max;
2020         }
2021     }
2022 
2023     private template hasNonObjectBaseType (T)
2024     {
2025         alias BaseTypes = BaseTypeTupleOf!(T);
2026         enum hasNonObjectBaseType = BaseTypes.length > 0 &&
2027             !is(Unqual!(BaseTypes[0]) == Object);
2028     }
2029 }
2030 
2031 /**
2032  * This struct is a type independent representation of an array. This struct is used
2033  * when sending an array for archiving from the serializer to the archive.
2034  */
2035 struct Array
2036 {
2037     const(void)* ptr;
2038 
2039     /// The length of the array
2040     size_t length;
2041 
2042     /// The size of an individual element stored in the array, in bytes.
2043     size_t elementSize;
2044 
2045     /**
2046      * Returns true if the given array is a slice of the receiver.
2047      *
2048      * Params:
2049      *     b = the array to check if it's a slice
2050      *
2051      * Returns: true if the given array is a slice of the receiver.
2052      */
2053     bool isSliceOf (Array b)
2054     {
2055         return ptr >= b.ptr && ptr + length * elementSize <= b.ptr + b.length * b.elementSize;
2056     }
2057 }
2058 
2059 /**
2060  * This struct is a type independent representation of a slice. This struct is used
2061  * when sending a slice for archiving from the serializer to the archive.
2062  */
2063 struct Slice
2064 {
2065     /// The length of the slice.
2066     size_t length;
2067 
2068     /// The offset of the slice, i.e. where the slice begins in the array.
2069     size_t offset;
2070 
2071     /// The id of the slice. (Only used during unarchiving).
2072     size_t id = size_t.max;
2073 }