コード例 #1
0
            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);
            }
コード例 #2
0
            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);
            }
コード例 #3
0
        /// <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);
            }
        }
コード例 #4
0
 /// <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);
     }
 }
コード例 #5
0
 /// <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);
     }
 }
コード例 #6
0
            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;
            }
コード例 #7
0
            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;
            }
コード例 #8
0
        /// <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);
        }
コード例 #9
0
        /// <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));
        }
コード例 #10
0
 /// <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));
 }