Mercurial > projects > orange
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++; |