changeset 25:b51e953f79eb experimental

Second step in refactoring the API.
author Jacob Carlborg <doob@me.com>
date Wed, 06 Oct 2010 16:18:02 +0200
parents 55f0a9d5df8d
children 78e5fef4bbf2
files dsss.conf orange/serialization/Serializer.d orange/serialization/archives/Archive.d orange/serialization/archives/XMLArchive.d
diffstat 4 files changed, 186 insertions(+), 379 deletions(-) [+]
line wrap: on
line diff
--- a/dsss.conf	Tue Oct 05 21:59:46 2010 +0200
+++ b/dsss.conf	Wed Oct 06 16:18:02 2010 +0200
@@ -1,1 +1,1 @@
-[orange]
\ No newline at end of file
+[main.d]
\ No newline at end of file
--- a/orange/serialization/Serializer.d	Tue Oct 05 21:59:46 2010 +0200
+++ b/orange/serialization/Serializer.d	Wed Oct 06 16:18:02 2010 +0200
@@ -33,76 +33,47 @@
 	alias Mode.deserializing deserializing;
 }
 
-class Serializer (ArchiveType : IArchive)
+class Serializer
 {
-	static assert(isArchive!(ArchiveType), format!(`The type "`, ArchiveType, `" does not implement the necessary methods to be an archive.`));
-	
-	alias ArchiveType.ErrorCallback ErrorCallback;
-	alias ArchiveType.DataType DataType;	
+	alias void delegate (ArchiveException exception, IArchive.IDataType data) ErrorCallback;
+	alias IArchive.IDataType DataType;
 	
 	private
 	{
-		ArchiveType archive;
+		ErrorCallback errorCallback_;		
+		IArchive archive;
+		
+		size_t keyCounter;
+		size_t idCounter;
 		
 		RegisterBase[string] serializers;
-		RegisterBase[string] deserializers;
-		
-		size_t keyCounter;
+		RegisterBase[string] deserializers;		
 		
 		bool hasBegunSerializing;
 		bool hasBegunDeserializing;
 		
-		void delegate (ArchiveException exception, DataType[] data) throwOnErrorCallback;		
-		void delegate (ArchiveException exception, DataType[] data) doNothingOnErrorCallback;
+		void delegate (ArchiveException exception, DataType data) throwOnErrorCallback;		
+		void delegate (ArchiveException exception, DataType data) doNothingOnErrorCallback;
 	}
 	
-	this ()
+	this (IArchive archive)
 	{
-		archive = new ArchiveType;
+		this.archive = archive;
 		
-		throwOnErrorCallback = (ArchiveException exception, DataType[] data) { throw exception; };
-		doNothingOnErrorCallback = (ArchiveException exception, DataType[] data) { /* do nothing */ };
+		throwOnErrorCallback = (ArchiveException exception, IArchive.IDataType data) { throw exception; };
+		doNothingOnErrorCallback = (ArchiveException exception, IArchive.IDataType data) { /* do nothing */ };
 		
 		setThrowOnErrorCallback();
 	}
-
-	void registerSerializer (T) (string type, void delegate (T, Serializer, DataType) dg)
-	{		
-		serializers[type] = toSerializeRegisterWrapper(dg);
-	}
-
-	void registerSerializer (T) (string type, void function (T, Serializer, DataType) func)
-	{		
-		serializers[type] = toSerializeRegisterWrapper(func);
-	}
-
-	void registerDeserializer (T) (string type, void delegate (ref T, Serializer, DataType) dg)
-	{		
-		deserializers[type] = toDeserializeRegisterWrapper(dg);
-	}
-
-	void registerDeserializer (T) (string type, void function (ref T, Serializer, DataType) func)
-	{		
-		deserializers[type] = toDeserializeRegisterWrapper(func);
-	}
-	
-	void reset ()
-	{
-		hasBegunSerializing = false;
-		hasBegunDeserializing = false;
-		resetCounters();
-		
-		archive.reset;
-	}
 	
 	ErrorCallback errorCallback ()
 	{
-		return archive.errorCallback;
+		return errorCallback_;
 	}
 	
 	ErrorCallback errorCallback (ErrorCallback errorCallback)
 	{
-		return archive.errorCallback = errorCallback;
+		return errorCallback_ = errorCallback;
 	}
 	
 	void setThrowOnErrorCallback ()
@@ -115,7 +86,7 @@
 		errorCallback = doNothingOnErrorCallback;
 	}
 	
-	DataType serialize (T) (T value, DataType key = null)
+	DataType serialize (T) (T value, string key = null)
 	{
 		if (!hasBegunSerializing)
 			hasBegunSerializing = true;
@@ -126,7 +97,7 @@
 		return archive.data;
 	}
 	
-	private void serializeInternal (T) (T value, DataType key = null)
+	private void serializeInternal (T) (T value, string key = null)
 	{
 		if (!key)
 			key = nextKey;
@@ -172,13 +143,13 @@
 			throw new SerializationException(format!(`The type "`, T, `" cannot be serialized.`), __FILE__, __LINE__);
 		}
 	}
-	
-	private void serializeObject (T) (T value, DataType key)
-	{			
+
+	private void serializeObject (T) (T value, string key)
+	{
+		auto runtimeType = value.classinfo.name; 
+		
 		triggerEvents(serializing, value, {
-			archive.archive(value, key, {
-				auto runtimeType = value.classinfo.name;
-
+			archive.archiveObject(runtimeType, T.stringof, key, nextId, {
 				if (runtimeType in serializers)
 				{
 					auto wrapper = getSerializerWrapper!(T)(runtimeType);
@@ -198,13 +169,13 @@
 			});
 		});
 	}
-
+	
 	private void serializeStruct (T) (T value, DataType key)
-	{		
+	{
+		auto type = T.stringof;
+		
 		triggerEvents(serializing, value, {
-			archive.archive(value, key, {
-				auto type = toDataType(T.stringof);
-				
+			archive.archive(type, key, nextId, {				
 				if (type in serializers)
 				{
 					auto wrapper = getSerializerWrapper!(T)(type);
@@ -223,244 +194,24 @@
 		});
 	}
 	
-	private void serializeString (T) (T value, DataType key)
+	private void serializeString (T) (T value, string key)
 	{
-		archive.archive(value, key);
+		archive.archive(value, key, nextId);
 	}
-
-	private void serializeArray (T) (T value, DataType key)
+	
+	private void serializeArray (T) (T value, string key)
 	{
-		archive.archive(value, key, {
+		auto array = Array(value.ptr, value.length, BaseTypeOfArray!(T).sizeof);
+		
+		archive.archiveArray(array, arrayToString!(T), key, nextId, {
 			foreach (i, e ; value)
 				serializeInternal(e, toDataType(i));
 		});
 	}
-
-	private void serializeAssociativeArray (T) (T value, DataType key)
-	{
-		archive.archive(value, key, {
-			foreach(k, v ; value)
-				serializeInternal(v, toDataType(k));
-		});
-	}
-
-	private void serializePointer (T) (T value, DataType key)
-	{
-		archive.archive(value, key, {
-			if (key in serializers)
-			{
-				auto wrapper = getSerializerWrapper!(T)(key);
-				wrapper(value, this, key);
-			}
-			
-			else static if (isSerializable!(T, Serializer))
-				value.toData(this, key);
-			
-			else
-			{
-				static if (isVoid!(BaseTypeOfPointer!(T)))
-					throw new SerializationException(`The value with the key "` ~ to!(string)(key) ~ `"` ~ format!(` of the type "`, T, `" cannot be serialized on its own, either implement orange.serialization.Serializable.isSerializable or register a serializer.`), __FILE__, __LINE__);
-				
-				else
-					serializeInternal(*value, key);
-			}				
-		});
-	}
 	
-	private void serializeEnum (T) (T value, DataType key)
-	{
-		archive.archive(value, key);
-	}
-
-	private void serializePrimitive (T) (T value, DataType key)
-	{		
-		archive.archive(value, key);
-	}
-	
-	private void serializeTypeDef (T) (T value, DataType key)
-	{
-		archive.archive(value, key, {
-			serializeInternal!(BaseTypeOfTypeDef!(T))(value, key);
-		});
-	}
-	
-	T deserialize (T) (DataType data, DataType key = null)
-	{		
-		if (hasBegunSerializing && !hasBegunDeserializing)
-			resetCounters();
-		
-		if (!hasBegunDeserializing)
-			hasBegunDeserializing = true;
-		
-		if (!key)
-			key = nextKey;
-		
-		archive.beginUnarchiving(data);
-		return deserializeInternal!(T)(key);
-	}
-	
-	private T deserializeInternal (T) (DataType key)
-	{
-		static if (isTypeDef!(T))
-			return deserializeTypeDef!(T)(key);
-		
-		else static if (isObject!(T))
-			return deserializeObject!(T)(key);
-
-		else static if (isStruct!(T))
-			return deserializeStruct!(T)(key);
-
-		else static if (isString!(T))
-			return deserializeString!(T)(key);
-		
-		else static if (isArray!(T))
-			return deserializeArray!(T)(key);
-
-		else static if (isAssociativeArray!(T))
-			return deserializeAssociativeArray!(T)(key);
-
-		else static if (isPrimitive!(T))
-			return deserializePrimitive!(T)(key);
-
-		else static if (isPointer!(T))
-		{			
-			static if (isFunctionPointer!(T))
-				goto error;
-			
-			return deserializePointer!(T)(key);
-		}		
-		
-		else static if (isEnum!(T))
-			return deserializeEnum!(T)(key);
-		
-		else
-		{
-			error:
-			throw new SerializationException(format!(`The type "`, T, `" cannot be deserialized.`), __FILE__, __LINE__);
-		}			
-	}
-
-	private T deserializeObject (T) (DataType key)
+	private void serializePrimitive (T) (T value, string key)
 	{		
-		T value = archive.unarchive!(T)(key, (T value) {			
-			triggerEvents(deserializing, value, {
-				auto runtimeType = value.classinfo.name;
-				
-				if (runtimeType in deserializers)
-				{
-					auto wrapper = getDeserializerWrapper!(T)(runtimeType);
-					wrapper(value, this, key);
-				}
-				
-				else static if (isSerializable!(T, Serializer))
-					value.fromData(this, key);
-				
-				else
-				{
-					if (isBaseClass(value))
-						throw new SerializationException(`The object of the static type "` ~ T.stringof ~ `" have a different runtime type (` ~ runtimeType ~ `) and therefore needs to register a deserializer for its type "` ~ runtimeType ~ `".`, __FILE__, __LINE__);
-					
-					objectStructDeserializeHelper(value);					
-				}
-			});
-			
-			return value;
-		});
-		
-		return value;
-	}
-
-	private T deserializeStruct (T) (DataType key)
-	{		
-		return archive.unarchive!(T)(key, (T value) {			
-			triggerEvents(deserializing, value, {
-				auto type = toDataType(T.stringof);
-				
-				if (type in deserializers)
-				{
-					auto wrapper = getDeserializerWrapper!(T)(type);
-					wrapper(value, this, key);
-				}
-				
-				else
-				{
-					static if (isSerializable!(T, Serializer))
-						value.fromData(this, key);
-					
-					else
-						objectStructDeserializeHelper(value);
-				}	
-			});
-			
-			return value;
-		});
-	}
-	
-	private T deserializeString (T) (DataType key)
-	{
-		return archive.unarchive!(T)(key);
-	}
-
-	private T deserializeArray (T) (DataType key)
-	{
-		return archive.unarchive!(T)(key, (T value) {
-			foreach (i, ref e ; value)
-				e = deserializeInternal!(typeof(e))(toDataType(i));
-			
-			return value;
-		});	
-	}
-
-	private T deserializeAssociativeArray (T) (DataType key)
-	{		
-		return archive.unarchive!(T)(key, (T value) {			
-			foreach (k, v ; archive.unarchiveAssociativeArrayVisitor!(T))
-				value[k] = v;
-			
-			return value;
-		});	
-	}
-
-	private T deserializePointer (T) (DataType key)
-	{
-		return archive.unarchive!(T)(key, (T value) {
-			if (key in deserializers)
-			{
-				auto wrapper = getDeserializerWrapper!(T)(key);
-				wrapper(value, this, key);
-			}
-			
-			else static if (isSerializable!(T, Serializer))
-				value.fromData(this, key);
-			
-			else
-			{
-				static if (isVoid!(BaseTypeOfPointer!(T)))
-					throw new SerializationException(`The value with the key "` ~ to!(string)(key) ~ `"` ~ format!(` of the type "`, T, `" cannot be deserialized on its own, either implement orange.serialization.Serializable.isSerializable or register a deserializer.`), __FILE__, __LINE__);
-				
-				else
-					*value = deserializeInternal!(BaseTypeOfPointer!(T))(key);
-			}
-			
-			return value;
-		});
-	}
-	
-	private T deserializeEnum (T) (DataType key)
-	{
-		return archive.unarchive!(T)(key);
-	}
-
-	private T deserializePrimitive (T) (DataType key)
-	{		
-		return archive.unarchive!(T)(key);
-	}
-	
-	private T deserializeTypeDef (T) (DataType key)
-	{
-		return archive.unarchive!(T)(key, (T value) {
-			return deserializeInternal!(BaseTypeOfTypeDef!(T))(key);
-		});
+		archive.archive(value, key, nextId);
 	}
 	
 	private void objectStructSerializeHelper (T) (ref T value)
@@ -511,7 +262,7 @@
 		
 		static if (!is(Base == Object))
 		{
-			archive.archiveBaseClass!(Base)(nextKey);
+			archive.archiveBaseClass(Base.stringof, nextKey, nextId);
 			Base base = value;
 			objectStructSerializeHelper(base);
 		}
@@ -549,33 +300,29 @@
 		assert(false, "throw exception here");
 	}
 	
-	private SerializeRegisterWrapper!(T, Serializer) toSerializeRegisterWrapper (T) (void delegate (T, Serializer, DataType) dg)
+	private SerializeRegisterWrapper!(T, Serializer) toSerializeRegisterWrapper (T) (void delegate (T, Serializer, string) dg)
 	{		
 		return new SerializeRegisterWrapper!(T, Serializer)(dg);
 	}
 
-	private SerializeRegisterWrapper!(T, Serializer) toSerializeRegisterWrapper (T) (void function (T, Serializer, DataType) func)
+	private SerializeRegisterWrapper!(T, Serializer) toSerializeRegisterWrapper (T) (void function (T, Serializer, string) func)
 	{		
 		return new SerializeRegisterWrapper!(T, Serializer)(func);
 	}
 
-	private DeserializeRegisterWrapper!(T, Serializer) toDeserializeRegisterWrapper (T) (void delegate (ref T, Serializer, DataType) dg)
+	private DeserializeRegisterWrapper!(T, Serializer) toDeserializeRegisterWrapper (T) (void delegate (ref T, Serializer, string) dg)
 	{		
 		return new DeserializeRegisterWrapper!(T, Serializer)(dg);
 	}
 
-	private DeserializeRegisterWrapper!(T, Serializer) toDeserializeRegisterWrapper (T) (void function (ref T, Serializer, DataType) func)
+	private DeserializeRegisterWrapper!(T, Serializer) toDeserializeRegisterWrapper (T) (void function (ref T, Serializer, string) func)
 	{		
 		return new DeserializeRegisterWrapper!(T, Serializer)(func);
 	}
 	
-	private DataType toDataType (T) (T value)
+	private template arrayToString (T)
 	{
-		try
-			return to!(DataType)(value);
-		
-		catch (ConversionException e)
-			throw new SerializationException(e);
+		const arrayToString = BaseTypeOfArray!(T).stringof;
 	}
 	
 	private bool isBaseClass (T) (T value)
@@ -586,7 +333,12 @@
 		return T.stringof != name[index + 1 .. $];
 	}
 	
-	private DataType nextKey ()
+	private size_t nextId ()
+	{
+		return idCounter++;
+	}
+	
+	private string nextKey ()
 	{
 		return toDataType(keyCounter++);
 	}
@@ -594,6 +346,12 @@
 	private void resetCounters ()
 	{
 		keyCounter = 0;
+		idCounter = 0;
+	}
+	
+	private string toDataType (T) (T value)
+	{
+		return to!(string)(value);
 	}
 	
 	private void triggerEvent (string name, T) (T value)
--- a/orange/serialization/archives/Archive.d	Tue Oct 05 21:59:46 2010 +0200
+++ b/orange/serialization/archives/Archive.d	Wed Oct 06 16:18:02 2010 +0200
@@ -18,22 +18,18 @@
 import orange.serialization.archives.ArchiveException;
 import orange.util.string;
 
+private enum ArchiveMode
+{
+	archiving,
+	unarchiving
+}
+
 struct Array
 {
 	void* ptr;
 	size_t length;
 	size_t elementSize;
 	
-	static Array opCall (T) (T[] value)
-	{
-		Array array;
-		array.ptr = value.ptr;
-		array.length = value.length;
-		array.elementSize = T.sizeof;
-		
-		return array;
-	}
-	
 	bool isSliceOf (Array b)
 	{
 		return ptr >= b.ptr && ptr + length * elementSize <= b.ptr + b.length * b.elementSize;
@@ -59,8 +55,8 @@
 	void postProcess ();
 	void reset ();
 	
-	void archiveArray (string type, size_t length, size_t elementSize, string key, size_t id);
-	void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id);
+	void archiveArray (Array array, string type, string key, size_t id, void delegate () dg);
+	void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id, void delegate () dg);
 	
 	void archiveEnum (bool value, string key, size_t id);
 	void archiveEnum (byte value, string key, size_t id);
@@ -75,31 +71,32 @@
 	void archiveEnum (ushort value, string key, size_t id);
 	void archiveEnum (wchar value, string key, size_t id);
 	
+	void archiveBaseClass (string type, string key, size_t id);
 	void archiveNull (string type, string key);
-	void archiveObject (string runtimeType, string type, string key, size_t id);
+	void archiveObject (string runtimeType, string type, string key, size_t id, void delegate () dg);
 	void archivePointer (string key, size_t id);
 	void archiveReference (string key, size_t id);
 	//void archiveSlice (size_t length, size_t offset, string key, size_t id);
-	void archiveStruct (string type, string key, size_t id);
-	void archiveTypedef (string type, string key, size_t id);
+	void archiveStruct (string type, string key, size_t id, void delegate () dg);
+	void archiveTypedef (string type, string key, size_t id, void delegate () dg);
 
 	void archive (string value, string key, size_t id);
 	void archive (wstring value, string key, size_t id);
 	void archive (dstring value, string key, size_t id);	
 	void archive (bool value, string key, size_t id);
 	void archive (byte value, string key, size_t id);
-	void archive (cdouble value, string key, size_t id);
+	//void archive (cdouble value, string key, size_t id);
 	//void archive (cent value, string key, size_t id);
-	void archive (cfloat value, string key, size_t id);
+	//void archive (cfloat value, string key, size_t id);
 	void archive (char value, string key, size_t id);
-	void archive (creal value, string key, size_t id);
+	//void archive (creal value, string key, size_t id);
 	void archive (dchar value, string key, size_t id);
 	void archive (double value, string key, size_t id);
 	void archive (float value, string key, size_t id);
-	void archive (idouble value, string key, size_t id);
-	void archive (ifloat value, string key, size_t id);
+	//void archive (idouble value, string key, size_t id);
+	//void archive (ifloat value, string key, size_t id);
 	void archive (int value, string key, size_t id);
-	void archive (ireal value, string key, size_t id);
+	//void archive (ireal value, string key, size_t id);
 	void archive (long value, string key, size_t id);
 	void archive (real value, string key, size_t id);
 	void archive (short value, string key, size_t id);
@@ -111,14 +108,19 @@
 	void archive (wchar value, string key, size_t id);
 }
 
-abstract class Archive (U) //: IArchive
+abstract class Archive (U) : IArchive
 {
 	version (Tango) alias U[] DataType;
 	else mixin ("alias immutable(U)[] DataType;");
 	
 	alias void delegate (ArchiveException exception, DataType[] data) ErrorCallback;
 	
-	ErrorCallback errorCallback;
+	protected ErrorCallback errorCallback;
+	
+	protected this (ErrorCallback errorCallback)
+	{
+		this.errorCallback = errorCallback;
+	}
 	
 	protected DataType toDataType (T) (T value)
 	{
--- a/orange/serialization/archives/XMLArchive.d	Tue Oct 05 21:59:46 2010 +0200
+++ b/orange/serialization/archives/XMLArchive.d	Wed Oct 06 16:18:02 2010 +0200
@@ -18,6 +18,8 @@
 
 final class XMLArchive (U = char) : Archive!(U)
 {
+	private alias IArchive.IDataType IDataType;
+	
 	private struct Tags
 	{
 		static const DataType structTag = "struct";	
@@ -49,6 +51,14 @@
 		static const DataType offsetAttribute = "offset";
 	}
 	
+	private struct ArrayNode
+	{
+		XMLDocument!(U).Node parent;
+		XMLDocument!(U).Node node;
+		DataType id;
+		DataType key;
+	}
+	
 	private
 	{
 		DataType archiveType = "org.dsource.orange.xml";
@@ -64,9 +74,9 @@
 		void[][DataType] unarchivedSlices;
 	}
 	
-	this (ErrorCallback errorCallback)
+	this (ErrorCallback errorCallback = null)
 	{
-		this.errorCallback = errorCallback;
+		super(errorCallback);
 		doc = new XMLDocument!(U);
 	}
 	
@@ -152,34 +162,37 @@
 		doc.reset;
 	}
 	
-	void archiveArray (Array array, string type, string key, size_t id)
+	void archiveArray (Array array, string type, string key, size_t id, void delegate () dg)
 	{
 		internalArchiveArray(type, array, key, id, Tags.arrayTag);
+		dg();
 	}
 	
 	private void internalArchiveArray(string type, Array array, string key, size_t id, DataType tag, DataType content = null)
 	{
 		auto parent = lastElement;
 		
-		if (value.length == 0)
+		if (array.length == 0)
 			lastElement = lastElement.element(tag);
 		
 		else
 			lastElement = doc.createNode(tag, content);			
 		
 		lastElement.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.lengthAttribute, toDataType(length))
+		.attribute(Attributes.lengthAttribute, toDataType(array.length))
 		.attribute(Attributes.keyAttribute, toDataType(key))
 		.attribute(Attributes.idAttribute, toDataType(id));
 	}
 	
-	void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id)
+	void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id, void delegate () dg)
 	{
 		lastElement = lastElement.element(Tags.associativeArrayTag)		
 		.attribute(Attributes.keyTypeAttribute, toDataType(keyType))
 		.attribute(Attributes.valueTypeAttribute, toDataType(valueType))
 		.attribute(Attributes.lengthAttribute, toDataType(length))
 		.attribute(Attributes.keyAttribute, key);
+		
+		dg();
 	}
 	
 	void archiveEnum (bool value, string key, size_t id)
@@ -249,20 +262,29 @@
 		.attribute(Attributes.keyAttribute, toDataType(key));
 	}
 	
+	void archiveBaseClass (string type, string key, size_t id)
+	{
+		lastElement = lastElement.element(Tags.baseTag)
+		.attribute(Attributes.typeAttribute, toDataType(type))
+		.attribute(Attributes.keyAttribute, toDataType(key)); 
+	}
+	
 	void archiveNull (string type, string key)
 	{
 		lastElement.element(Tags.nullTag)
-		.attribute(Attributes.typeAttribute, toDataType(T.stringof))
-		.attribute(Attributes.keyAttribute, key);
+		.attribute(Attributes.typeAttribute, toDataType(type))
+		.attribute(Attributes.keyAttribute, toDataType(key));
 	}
 	
-	void archiveObject (string runtimeType, string type, string key, size_t id)
+	void archiveObject (string runtimeType, string type, string key, size_t id, void delegate () dg)
 	{
 		lastElement = lastElement.element(Tags.objectTag)
-		.attribute(Attributes.runtimeTypeAttribute, toDataType(name))
+		.attribute(Attributes.runtimeTypeAttribute, toDataType(runtimeType))
 		.attribute(Attributes.typeAttribute, toDataType(type))
 		.attribute(Attributes.keyAttribute, toDataType(key))
-		.attribute(Attributes.idAttribute, toDataType(id));		
+		.attribute(Attributes.idAttribute, toDataType(id));
+		
+		dg();
 	}
 	
 	void archivePointer (string key, size_t id)
@@ -272,7 +294,7 @@
 		.attribute(Attributes.idAttribute, toDataType(id));
 	}
 	
-	void archiveReference (size_t key, size_t id)
+	void archiveReference (string key, size_t id)
 	{
 		lastElement.element(Tags.referenceTag, toDataType(id))
 		.attribute(Attributes.keyAttribute, toDataType(key));
@@ -286,18 +308,22 @@
 		.attribute(Attributes.lengthAttribute, toDataType(slice.length));
 	}*/
 	
-	void archiveStruct (string type, size_t key, size_t id)
+	void archiveStruct (string type, string key, size_t id, void delegate () dg)
 	{
 		lastElement = lastElement.element(Tags.structTag)
 		.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.keyAttribute, key);
+		.attribute(Attributes.keyAttribute, toDataType(key));
+		
+		dg();
 	}
 	
-	void archiveTypedef (string type, size_t key, size_t id)
+	void archiveTypedef (string type, string key, size_t id, void delegate () dg)
 	{
 		lastElement = lastElement.element(Tags.typedefTag)
-		.attribute(Attributes.typeAttribute, toDataType(type));
-		.attribute(Attributes.key, toDataType(key));
+		.attribute(Attributes.typeAttribute, toDataType(type))
+		.attribute(Attributes.keyAttribute, toDataType(key));
+		
+		dg();
 	}
 	
 	void archive (string value, string key, size_t id)
@@ -325,117 +351,117 @@
 	
 	void archive (bool value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (byte value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
-	void archive (cdouble value, string key, size_t id)
+	/*void archive (cdouble value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
-	}
+		archivePrimitive(value, key);
+	}*/
 	
 	/*void archive (cent value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}*/
 	
-	void archive (cfloat value, string key, size_t id)
+	/*void archive (cfloat value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
-	}
+		archivePrimitive(value, key);
+	}*/
 	
 	void archive (char value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
-	void archive (creal value, string key, size_t id)
+	/*void archive (creal value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
-	}
+		archivePrimitive(value, key);
+	}*/
 	
 	void archive (dchar value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (double value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (float value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
-	void archive (idouble value, string key, size_t id)
+	/*void archive (idouble value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
-	}
+		archivePrimitive(value, key);
+	}*/
 	
-	void archive (ifloat value, string key, size_t id)
+	/*void archive (ifloat value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
-	}
+		archivePrimitive(value, key);
+	}*/
 	
 	void archive (int value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
-	void archive (ireal value, string key, size_t id)
+	/*void archive (ireal value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
-	}
+		archivePrimitive(value, key);
+	}*/
 	
 	void archive (long value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (real value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (short value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (ubyte value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	/*void archive (ucent value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}*/
 	
 	void archive (uint value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (ulong value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (ushort value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}
 	
 	void archive (wchar value, string key, size_t id)
 	{
-		archivePrimitive (value, key);
+		archivePrimitive(value, key);
 	}	
 	
 	private void archivePrimitive (T) (T value, string key)
@@ -444,8 +470,29 @@
 		.attribute(Attributes.keyAttribute, toDataType(key));
 	}
 	
-	private void addArchivedArray (doc.Node parent, doc.Node lastElement, size_t id, string key, size_t elementSize, )
+	version (Tango)
 	{
-		arraysToBeArchived[Array(value)] = ArrayNode(parent, lastElement, id, key);
-	}	
+		private template errorMessage (ArchiveMode mode = ArchiveMode.archiving)
+		{
+			static if (mode == ArchiveMode.archiving)
+				const errorMessage = "Could not continue archiving due to unrecognized data format: ";
+				
+			else static if (mode == ArchiveMode.unarchiving)
+				const errorMessage = "Could not continue unarchiving due to unrecognized data format: ";
+		}
+	}
+	
+	else
+	{
+		mixin(
+			`private template errorMessage (ArchiveMode mode = ArchiveMode.archiving)
+			{
+				static if (mode == ArchiveMode.archiving)
+					enum errorMessage = "Could not continue archiving due to unrecognized data format: ";
+					
+				else static if (mode == ArchiveMode.unarchiving)
+					enum errorMessage = "Could not continue unarchiving due to unrecognized data format: ";
+			}`
+		);
+	}
 }
\ No newline at end of file