public object PreSerialize(TagElementAttribute info, object obj) { if (obj == null) { return(null); } // Get the object type and make sure it's supported var type = obj.GetType(); if (type == typeof(ResourceDataReference) || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(D3DPointer <>))) { throw new InvalidOperationException(type + " cannot be serialized as tag data"); } if (type == typeof(HaloTag)) { // Object is a tag reference - add it as a dependency var referencedTag = obj as HaloTag; if (referencedTag != null) { _context._dependencies.Add(referencedTag.Index); } } return(obj); }
public object PreSerialize(TagElementAttribute info, object obj) { if (obj == null) { return(null); } // When serializing a resource address, just add a fixup for it and serialize a null pointer if (obj is ResourceAddress) { _fixups.Add(MakeDefinitionFixup((ResourceAddress)obj)); return(0U); } var type = obj.GetType(); if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(D3DPointer <>)) { // Add a D3D fixup for D3DPointers based on the type of object being pointed to var d3dType = GetD3DObjectType(type.GenericTypeArguments[0]); _d3dFixups.Add(MakeD3DFixup((uint)Stream.Position, d3dType)); } return(obj); }
/// <summary> /// Serializes an inline array. /// </summary> /// <param name="context">The serialization context to use.</param> /// <param name="tagStream">The stream to write completed blocks of tag data to.</param> /// <param name="block">The temporary block to write incomplete tag data to.</param> /// <param name="data">The array.</param> /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param> private static void SerializeInlineArray(ISerializationContext context, MemoryStream tagStream, IDataBlock block, Array data, TagElementAttribute valueInfo) { if (valueInfo == null || valueInfo.Count == 0) { throw new ArgumentException("Cannot serialize an inline array with no count set"); } if (data == null || data.Length != valueInfo.Count) { throw new ArgumentException("Array length does not match the fixed count of " + valueInfo.Count); } // Serialize each element into the current block var elementType = data.GetType().GetElementType(); foreach (var elem in data) { SerializeValue(context, tagStream, block, elem, null, elementType); } }
/// <summary> /// Serializes a complex value. /// </summary> /// <param name="context">The serialization context to use.</param> /// <param name="tagStream">The stream to write completed blocks of tag data to.</param> /// <param name="block">The temporary block to write incomplete tag data to.</param> /// <param name="val">The value.</param> /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param> /// <param name="valueType">Type of the value.</param> private static void SerializeComplexValue(ISerializationContext context, MemoryStream tagStream, IDataBlock block, object val, TagElementAttribute valueInfo, Type valueType) { if (valueInfo != null && ((valueInfo.Flags & TagElementFlags.Indirect) != 0 || valueType == typeof(ResourceReference))) { SerializeIndirectValue(context, tagStream, block, val, valueType); } else if (valueType.IsEnum) { SerializePrimitiveValue(block.Writer, val, valueType.GetEnumUnderlyingType()); } else if (valueType == typeof(string)) { SerializeString(block.Writer, (string)val); } else if (valueType == typeof(HaloTag)) { SerializeTagReference(block.Writer, (HaloTag)val); } else if (valueType == typeof(ResourceAddress)) { block.Writer.Write(((ResourceAddress)val).Value); } else if (valueType == typeof(byte[])) { SerializeDataReference(tagStream, block, (byte[])val); } else if (valueType == typeof(Vector2)) { SerializeVector(block, (Vector2)val); } else if (valueType == typeof(Vector3)) { SerializeVector(block, (Vector3)val); } else if (valueType == typeof(Vector4)) { SerializeVector(block, (Vector4)val); } else if (valueType.IsArray) { SerializeInlineArray(context, tagStream, block, (Array)val, valueInfo); } else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List <>)) { SerializeTagBlock(context, tagStream, block, val, valueType); } else { SerializeStruct(context, tagStream, block, val); } }
/// <summary> /// Serializes a value. /// </summary> /// <param name="context">The serialization context to use.</param> /// <param name="tagStream">The stream to write completed blocks of tag data to.</param> /// <param name="block">The temporary block to write incomplete tag data to.</param> /// <param name="val">The value.</param> /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param> /// <param name="valueType">Type of the value.</param> private static void SerializeValue(ISerializationContext context, MemoryStream tagStream, IDataBlock block, object val, TagElementAttribute valueInfo, Type valueType) { // Call the data block's PreSerialize callback to determine if the value should be mutated val = block.PreSerialize(valueInfo, val); if (val != null) { valueType = val.GetType(); // TODO: Fix hax } if (valueType.IsPrimitive) { SerializePrimitiveValue(block.Writer, val, valueType); } else { SerializeComplexValue(context, tagStream, block, val, valueInfo, valueType); } }
public object PreSerialize(TagElementAttribute info, object obj) { if (obj == null) return null; // When serializing a resource address, just add a fixup for it and serialize a null pointer if (obj is ResourceAddress) { _fixups.Add(MakeDefinitionFixup((ResourceAddress)obj)); return 0U; } var type = obj.GetType(); if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(D3DPointer<>)) { // Add a D3D fixup for D3DPointers based on the type of object being pointed to var d3dType = GetD3DObjectType(type.GenericTypeArguments[0]); _d3dFixups.Add(MakeD3DFixup((uint)Stream.Position, d3dType)); } return obj; }
public object PreSerialize(TagElementAttribute info, object obj) { if (obj == null) return null; // Get the object type and make sure it's supported var type = obj.GetType(); if (type == typeof(ResourceDataReference) || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(D3DPointer<>))) throw new InvalidOperationException(type + " cannot be serialized as tag data"); if (type == typeof(HaloTag)) { // Object is a tag reference - add it as a dependency var referencedTag = obj as HaloTag; if (referencedTag != null) _context._dependencies.Add(referencedTag.Index); } return obj; }
/// <summary> /// Deserializes an inline array. /// </summary> /// <param name="reader">The reader.</param> /// <param name="context">The serialization context to use.</param> /// <param name="valueInfo">The value information. Can be <c>null</c>.</param> /// <param name="valueType">The type of the value to deserialize.</param> /// <returns>The deserialized array.</returns> private static Array DeserializeInlineArray(BinaryReader reader, ISerializationContext context, TagElementAttribute valueInfo, Type valueType) { if (valueInfo == null || valueInfo.Count == 0) { throw new ArgumentException("Cannot deserialize an inline array with no count set"); } // Create the array and read the elements in order var elementCount = valueInfo.Count; var elementType = valueType.GetElementType(); var result = Array.CreateInstance(elementType, elementCount); for (var i = 0; i < elementCount; i++) { result.SetValue(DeserializeValue(reader, context, null, elementType), i); } return(result); }
/// <summary> /// Deserializes a complex value. /// </summary> /// <param name="reader">The reader.</param> /// <param name="context">The serialization context to use.</param> /// <param name="valueInfo">The value information. Can be <c>null</c>.</param> /// <param name="valueType">The type of the value to deserialize.</param> /// <returns>The deserialized value.</returns> private static object DeserializeComplexValue(BinaryReader reader, ISerializationContext context, TagElementAttribute valueInfo, Type valueType) { // Indirect objects // TODO: Remove ResourceReference hax, the Indirect flag wasn't available when I generated the tag structures if (valueInfo != null && ((valueInfo.Flags & TagElementFlags.Indirect) != 0 || valueType == typeof(ResourceReference))) { return(DeserializeIndirectValue(reader, context, valueType)); } // enum = Enum type if (valueType.IsEnum) { return(DeserializePrimitiveValue(reader, valueType.GetEnumUnderlyingType())); } // string = ASCII string if (valueType == typeof(string)) { return(DeserializeString(reader)); } // HaloTag = Tag reference if (valueType == typeof(HaloTag)) { return(DeserializeTagReference(reader, context)); } // ResourceAddress = Resource address if (valueType == typeof(ResourceAddress)) { return(new ResourceAddress(reader.ReadUInt32())); } // Byte array = Data reference // TODO: Allow other types to be in data references, since sometimes they can point to a structure if (valueType == typeof(byte[])) { return(DeserializeDataReference(reader, context)); } // Vector types if (valueType == typeof(Vector2)) { return(new Vector2(reader.ReadSingle(), reader.ReadSingle())); } if (valueType == typeof(Vector3)) { return(new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle())); } if (valueType == typeof(Vector4)) { return(new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle())); } // Non-byte array = Inline array // TODO: Define more clearly in general what constitutes a data reference and what doesn't if (valueType.IsArray) { return(DeserializeInlineArray(reader, context, valueInfo, valueType)); } // List = Tag block if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List <>)) { return(DeserializeTagBlock(reader, context, valueType)); } // Assume the value is a structure return(DeserializeStruct(reader, context, valueType)); }
/// <summary> /// Deserializes a value. /// </summary> /// <param name="reader">The reader.</param> /// <param name="context">The serialization context to use.</param> /// <param name="valueInfo">The value information. Can be <c>null</c>.</param> /// <param name="valueType">The type of the value to deserialize.</param> /// <returns>The deserialized value.</returns> private static object DeserializeValue(BinaryReader reader, ISerializationContext context, TagElementAttribute valueInfo, Type valueType) { if (valueType.IsPrimitive) { return(DeserializePrimitiveValue(reader, valueType)); } return(DeserializeComplexValue(reader, context, valueInfo, valueType)); }