private object ReadElement(MemberDefinition definition, object node, Type propertyType, object parent) { #if DEBUG_GR2_SERIALIZATION var offsetInFile = Stream.Position; #endif var kind = definition.SerializationKind; Debug.Assert(kind == SerializationKind.Builtin || !definition.IsScalar); if (node == null && propertyType != null && !definition.IsScalar && (kind == SerializationKind.Builtin || kind == SerializationKind.UserElement) && // Variant construction is a special case as we don't know the struct defn beforehand definition.Type != MemberType.VariantReference) { node = Helpers.CreateInstance(propertyType); } switch (definition.Type) { case MemberType.Inline: Debug.Assert(definition.Definition.IsValid); #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(String.Format(" === Inline Struct {0} === ", definition.Name)); #endif if (kind == SerializationKind.UserElement || kind == SerializationKind.UserMember) { node = definition.Serializer.Read(this, definition.Definition.Resolve(this), definition, 0, parent); } else { node = ReadStruct(definition.Definition.Resolve(this), definition.Type, node, parent); } #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(" === End Struct === "); #endif break; case MemberType.Reference: { Debug.Assert(definition.Definition.IsValid); var r = ReadReference(); if (r.IsValid && parent != null) { var originalPos = Stream.Position; Seek(r); #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(String.Format(" === Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position)); #endif if (kind == SerializationKind.UserElement || kind == SerializationKind.UserMember) { node = definition.Serializer.Read(this, definition.Definition.Resolve(this), definition, 0, parent); } else { node = ReadStruct(definition.Definition.Resolve(this), definition.Type, node, parent); } #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(" === End Struct === "); #endif Stream.Seek(originalPos, SeekOrigin.Begin); } else { node = null; } break; } case MemberType.VariantReference: { var structRef = ReadStructReference(); var r = ReadReference(); if (r.IsValid && parent != null) { var structDefn = structRef.Resolve(this); if (definition.TypeSelector != null && definition.Type == MemberType.VariantReference) { propertyType = definition.TypeSelector.SelectType(definition, structDefn, parent); } if (propertyType != null) { node = Helpers.CreateInstance(propertyType); } if (node != null) { var originalPos = Stream.Position; Seek(r); #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(String.Format(" === Variant Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position)); #endif if (kind == SerializationKind.UserElement || kind == SerializationKind.UserMember) { node = definition.Serializer.Read(this, structDefn, definition, 0, parent); } else { node = ReadStruct(structRef.Resolve(this), definition.Type, node, parent); } #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(" === End Struct === "); #endif Stream.Seek(originalPos, SeekOrigin.Begin); } } else { node = null; } break; } case MemberType.ArrayOfReferences: { // Serializing as a struct member is nooooot a very good idea here. Debug.Assert(kind != SerializationKind.UserMember); Debug.Assert(definition.Definition.IsValid); var indices = ReadArrayIndicesReference(); #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(String.Format(" Array of references at [{0:X8}]", indices.Offset)); #endif Debug.Assert(indices.IsValid == (indices.Size != 0)); if (indices.IsValid && node != null && parent != null) { var items = node as System.Collections.IList; var type = items.GetType().GetGenericArguments().Single(); var refs = indices.Resolve(this); var originalPos = Stream.Position; for (int i = 0; i < refs.Count; i++) { Seek(refs[i]); #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(String.Format(" === Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position)); #endif if (kind == SerializationKind.UserElement) { object element = definition.Serializer.Read(this, definition.Definition.Resolve(this), definition, 0, parent); items.Add(element); } else { object element = Helpers.CreateInstance(type); // TODO: Only create a new instance if we don't have a CachedStruct available! element = ReadStruct(definition.Definition.Resolve(this), definition.Type, element, parent); items.Add(element); } #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(" === End Struct === "); #endif } Stream.Seek(originalPos, SeekOrigin.Begin); node = items; } else { node = null; } break; } case MemberType.ReferenceToArray: case MemberType.ReferenceToVariantArray: { StructReference structRef; if (definition.Type == MemberType.ReferenceToVariantArray) { structRef = ReadStructReference(); } else { structRef = definition.Definition; } var itemsRef = ReadArrayReference(); Debug.Assert(itemsRef.IsValid == (itemsRef.Size != 0)); if (itemsRef.IsValid && parent != null && (node != null || kind == SerializationKind.UserMember)) { Debug.Assert(structRef.IsValid); var structType = structRef.Resolve(this); var originalPos = Stream.Position; Seek(itemsRef); if (kind == SerializationKind.UserMember) { // For ReferenceTo(Variant)Array, we start serialization after resolving the array ref itself. node = definition.Serializer.Read(this, structType, definition, itemsRef.Size, parent); } else { var items = node as System.Collections.IList; var type = items.GetType().GetGenericArguments().Single(); if (definition.Type == MemberType.ReferenceToVariantArray && kind != SerializationKind.UserElement && definition.TypeSelector != null) { type = definition.TypeSelector.SelectType(definition, structType, parent); } for (int i = 0; i < itemsRef.Size; i++) { #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(String.Format(" === Struct <{0}> at {1:X8} === ", definition.Name, Stream.Position)); #endif if (kind == SerializationKind.UserElement) { object element = definition.Serializer.Read(this, structType, definition, 0, parent); items.Add(element); } else { object element = Helpers.CreateInstance(type); element = ReadStruct(structType, definition.Type, element, parent); items.Add(element); } #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(" === End Struct === "); #endif } } Stream.Seek(originalPos, SeekOrigin.Begin); } else { node = null; } break; } case MemberType.String: var str = ReadStringReference(); if (str.IsValid) { node = str.Resolve(this); } else { node = null; } break; case MemberType.Transform: var transform = new Transform(); transform.Flags = Reader.ReadUInt32(); for (int i = 0; i < 3; i++) { transform.Translation[i] = Reader.ReadSingle(); } transform.Rotation.X = Reader.ReadSingle(); transform.Rotation.Y = Reader.ReadSingle(); transform.Rotation.Z = Reader.ReadSingle(); transform.Rotation.W = Reader.ReadSingle(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { transform.ScaleShear[i, j] = Reader.ReadSingle(); } } node = transform; break; case MemberType.Real16: throw new NotImplementedException("TODO"); case MemberType.Real32: node = Reader.ReadSingle(); break; case MemberType.Int8: case MemberType.BinormalInt8: node = Reader.ReadSByte(); break; case MemberType.UInt8: case MemberType.NormalUInt8: node = Reader.ReadByte(); break; case MemberType.Int16: case MemberType.BinormalInt16: node = Reader.ReadInt16(); break; case MemberType.UInt16: case MemberType.NormalUInt16: node = Reader.ReadUInt16(); break; case MemberType.Int32: node = Reader.ReadInt32(); break; case MemberType.UInt32: node = Reader.ReadUInt32(); break; default: throw new ParsingException(String.Format("Unhandled member type: {0}", definition.Type.ToString())); } #if DEBUG_GR2_SERIALIZATION if (node != null) { System.Console.WriteLine(String.Format(" [{0:X8}] {1}: {2}", offsetInFile, definition.Name, node.ToString())); } else { System.Console.WriteLine(String.Format(" [{0:X8}] {1}: <null>", offsetInFile, definition.Name)); } #endif return(node); }
internal object ReadInstance(MemberDefinition definition, object node, Type propertyType, object parent) { if (definition.SerializationKind == SerializationKind.UserRaw) { return(definition.Serializer.Read(this, null, definition, 0, parent)); } if (definition.ArraySize == 0) { return(ReadElement(definition, node, propertyType, parent)); } Type elementType = null; if (propertyType != null) { if (definition.SerializationKind == SerializationKind.UserMember) { // Do unserialization directly on the whole array if per-member serialization was requested. // This mode is a bit odd, as we resolve StructRef-s for non-arrays, but don't for array types. StructDefinition defn = null; if (definition.Definition.IsValid) { defn = definition.Definition.Resolve(this); } return(definition.Serializer.Read(this, defn, definition, definition.ArraySize, parent)); } else if (propertyType.IsArray) { // If the property is a native array (ie. SomeType[]), create an array instance and set its values elementType = propertyType.GetElementType(); Array objs = Helpers.CreateArrayInstance(propertyType, (int)definition.ArraySize) as Array; for (int i = 0; i < definition.ArraySize; i++) { objs.SetValue(ReadElement(definition, objs.GetValue(i), elementType, parent), i); } return(objs); } else { // For non-native arrays we always assume the property is an IList<T> if (node == null) { node = Helpers.CreateInstance(propertyType); } var items = node as System.Collections.IList; var type = items.GetType().GetGenericArguments().Single(); for (int i = 0; i < definition.ArraySize; i++) { items.Add(ReadElement(definition, null, elementType, parent)); } return(items); } } else { for (int i = 0; i < definition.ArraySize; i++) { ReadElement(definition, null, null, parent); } return(null); } }