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