diff orange/serialization/Serializer.d @ 49:beb4afce2f3e

Fixed (de)serializing through base class reference, including unit test.
author Jacob Carlborg <doob@me.com>
date Sat, 13 Aug 2011 15:57:19 +0200
parents a7dea44fa9e3
children
line wrap: on
line diff
--- a/orange/serialization/Serializer.d	Sat Aug 13 15:24:52 2011 +0200
+++ b/orange/serialization/Serializer.d	Sat Aug 13 15:57:19 2011 +0200
@@ -56,13 +56,15 @@
 			Id id;
 			string key;
 		}
-		
+
 		ErrorCallback errorCallback_;		
 		Archive archive_;
 		
 		size_t keyCounter;
 		Id idCounter;
 		
+		void delegate (Object, Mode mode) [ClassInfo] registeredTypes;
+		
 		RegisterBase[string] serializers;
 		RegisterBase[string] deserializers;
 		
@@ -95,6 +97,24 @@
 		setThrowOnErrorCallback();
 	}
 	
+	void register (T : Object) ()
+	{
+		registeredTypes[T.classinfo] = &downcastSerialize!(T);
+	}
+	
+	private void downcastSerialize (T : Object) (Object value, Mode mode)
+	{
+		auto casted = cast(T) value;
+		assert(casted);
+		assert(casted.classinfo is T.classinfo);
+		
+		if (mode == serializing)
+			objectStructSerializeHelper(casted);
+		
+		else
+			objectStructDeserializeHelper(casted);
+	}
+	
 	Archive archive ()
 	{
 		return archive_;
@@ -126,6 +146,7 @@
 		
 		serializers = null;
 		deserializers = null;
+		registeredTypes = null;
 		
 		serializedReferences = null;
 		deserializedReferences = null;
@@ -134,7 +155,10 @@
 		deserializedSlices = null;
 		
 		serializedValues = null;
+		deserializedValues = null;
+
 		serializedPointers = null;
+		deserializedPointers = null;
 		
 		hasBegunSerializing = false;
 		hasBegunDeserializing = false;
@@ -231,9 +255,20 @@
 				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 serializer for its type "` ~ runtimeType ~ `".`, __FILE__, __LINE__);
-
-					objectStructSerializeHelper(value);
+					{
+						if (auto serializer = value.classinfo in registeredTypes)
+							(*serializer)(value, serializing);
+						
+						else
+							throw new SerializationException(
+								`The object of the static type "` ~ T.stringof ~
+								`" have a different runtime type (` ~ runtimeType ~
+								`) and therefore needs to either register its type or register a serializer for its type "`
+								~ runtimeType ~ `".`, __FILE__, __LINE__);
+					}
+					
+					else
+						objectStructSerializeHelper(value);
 				}
 			});
 		});
@@ -469,9 +504,20 @@
 				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__);
+					{
+						if (auto deserializer = value.classinfo in registeredTypes)
+							(*deserializer)(value, deserializing);
 
-					objectStructDeserializeHelper(value);					
+						else
+							throw new SerializationException(
+								`The object of the static type "` ~ T.stringof ~
+								`" have a different runtime type (` ~ runtimeType ~
+								`) and therefore needs to either register its type or register a deserializer for its type "`
+								~ runtimeType ~ `".`, __FILE__, __LINE__);
+					}
+					
+					else
+						objectStructDeserializeHelper(value);					
 				}
 			});
 		});
@@ -995,10 +1041,7 @@
 	
 	private bool isBaseClass (T) (T value)
 	{
-		auto name = value.classinfo.name;		
-		auto index = name.lastIndexOf('.');
-		
-		return T.stringof != name[index + 1 .. $];
+		return value.classinfo !is T.classinfo;
 	}
 	
 	private Id nextId ()