comparison 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
comparison
equal deleted inserted replaced
48:a7dea44fa9e3 49:beb4afce2f3e
54 struct ValueMeta 54 struct ValueMeta
55 { 55 {
56 Id id; 56 Id id;
57 string key; 57 string key;
58 } 58 }
59 59
60 ErrorCallback errorCallback_; 60 ErrorCallback errorCallback_;
61 Archive archive_; 61 Archive archive_;
62 62
63 size_t keyCounter; 63 size_t keyCounter;
64 Id idCounter; 64 Id idCounter;
65 65
66 void delegate (Object, Mode mode) [ClassInfo] registeredTypes;
67
66 RegisterBase[string] serializers; 68 RegisterBase[string] serializers;
67 RegisterBase[string] deserializers; 69 RegisterBase[string] deserializers;
68 70
69 Id[void*] serializedReferences; 71 Id[void*] serializedReferences;
70 void*[Id] deserializedReferences; 72 void*[Id] deserializedReferences;
93 doNothingOnErrorCallback = (ArchiveException exception, string[] data) { /* do nothing */ }; 95 doNothingOnErrorCallback = (ArchiveException exception, string[] data) { /* do nothing */ };
94 96
95 setThrowOnErrorCallback(); 97 setThrowOnErrorCallback();
96 } 98 }
97 99
100 void register (T : Object) ()
101 {
102 registeredTypes[T.classinfo] = &downcastSerialize!(T);
103 }
104
105 private void downcastSerialize (T : Object) (Object value, Mode mode)
106 {
107 auto casted = cast(T) value;
108 assert(casted);
109 assert(casted.classinfo is T.classinfo);
110
111 if (mode == serializing)
112 objectStructSerializeHelper(casted);
113
114 else
115 objectStructDeserializeHelper(casted);
116 }
117
98 Archive archive () 118 Archive archive ()
99 { 119 {
100 return archive_; 120 return archive_;
101 } 121 }
102 122
124 { 144 {
125 resetCounters(); 145 resetCounters();
126 146
127 serializers = null; 147 serializers = null;
128 deserializers = null; 148 deserializers = null;
149 registeredTypes = null;
129 150
130 serializedReferences = null; 151 serializedReferences = null;
131 deserializedReferences = null; 152 deserializedReferences = null;
132 153
133 serializedArrays = null; 154 serializedArrays = null;
134 deserializedSlices = null; 155 deserializedSlices = null;
135 156
136 serializedValues = null; 157 serializedValues = null;
158 deserializedValues = null;
159
137 serializedPointers = null; 160 serializedPointers = null;
161 deserializedPointers = null;
138 162
139 hasBegunSerializing = false; 163 hasBegunSerializing = false;
140 hasBegunDeserializing = false; 164 hasBegunDeserializing = false;
141 165
142 archive.reset; 166 archive.reset;
229 value.toData(this, key); 253 value.toData(this, key);
230 254
231 else 255 else
232 { 256 {
233 if (isBaseClass(value)) 257 if (isBaseClass(value))
234 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__); 258 {
235 259 if (auto serializer = value.classinfo in registeredTypes)
236 objectStructSerializeHelper(value); 260 (*serializer)(value, serializing);
261
262 else
263 throw new SerializationException(
264 `The object of the static type "` ~ T.stringof ~
265 `" have a different runtime type (` ~ runtimeType ~
266 `) and therefore needs to either register its type or register a serializer for its type "`
267 ~ runtimeType ~ `".`, __FILE__, __LINE__);
268 }
269
270 else
271 objectStructSerializeHelper(value);
237 } 272 }
238 }); 273 });
239 }); 274 });
240 } 275 }
241 276
467 value.fromData(this, keyOrId); 502 value.fromData(this, keyOrId);
468 503
469 else 504 else
470 { 505 {
471 if (isBaseClass(value)) 506 if (isBaseClass(value))
472 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__); 507 {
473 508 if (auto deserializer = value.classinfo in registeredTypes)
474 objectStructDeserializeHelper(value); 509 (*deserializer)(value, deserializing);
510
511 else
512 throw new SerializationException(
513 `The object of the static type "` ~ T.stringof ~
514 `" have a different runtime type (` ~ runtimeType ~
515 `) and therefore needs to either register its type or register a deserializer for its type "`
516 ~ runtimeType ~ `".`, __FILE__, __LINE__);
517 }
518
519 else
520 objectStructDeserializeHelper(value);
475 } 521 }
476 }); 522 });
477 }); 523 });
478 524
479 addDeserializedReference(value, id); 525 addDeserializedReference(value, id);
993 mixin(`enum arrayToString = ElementTypeOfArray!(T).stringof;`); 1039 mixin(`enum arrayToString = ElementTypeOfArray!(T).stringof;`);
994 } 1040 }
995 1041
996 private bool isBaseClass (T) (T value) 1042 private bool isBaseClass (T) (T value)
997 { 1043 {
998 auto name = value.classinfo.name; 1044 return value.classinfo !is T.classinfo;
999 auto index = name.lastIndexOf('.');
1000
1001 return T.stringof != name[index + 1 .. $];
1002 } 1045 }
1003 1046
1004 private Id nextId () 1047 private Id nextId ()
1005 { 1048 {
1006 return idCounter++; 1049 return idCounter++;