diff orange/serialization/Serializer.d @ 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 9a575087b961
children 78e5fef4bbf2
line wrap: on
line diff
--- 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)