Пример #1
0
        /// <summary>
        ///    Unserializes the fields of an object from a binary reader.
        /// </summary>
        /// <param name="writer">Writer to unpack fields into.</param>
        /// <param name="obj">Object to unpack fields of.</param>
        private void UnPackObjectFields(BinaryReader reader, object obj)
        {
            // Write in field values.
            FieldInfo[] properties = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            // Order fields by names in alphabetical order.
            properties = properties.OrderBy(j => j.Name).ToArray();

            // Read number of fields.
            byte fieldCount = reader.ReadByte();
            if (properties.Length != fieldCount)
            {
                throw new IndexOutOfRangeException("Packet contains an invalid number of fields.");
            }

            // Read in fields hash and check if its correct.
            byte realHash = reader.ReadByte();
            PearsonHash hash = new PearsonHash();
            foreach (FieldInfo field in properties)
            {
                byte[] bytes = StringHelper.StringToByteArray(field.Name);
                hash.AddBuffer(bytes, 0, bytes.Length);
            }

            // Check hash is correct.
            if (hash.Calculate() != realHash)
            {
                throw new FormatException("Packet structure appears to be different from packet class.");
            }

            for (int i = 0; i < fieldCount; i++)
            {
                PacketPackedFieldType fieldType = (PacketPackedFieldType)reader.ReadByte();
                FieldInfo field                 = properties[i];
                Type realFieldType              = field.FieldType;

                // Is array or normal?
                if (((byte)fieldType & (byte)PacketPackedFieldType.Array) != 0)
                {
                    // Is field an array.
                    if (realFieldType.IsArray != true)
                    {
                        throw new FormatException("Packet contains invalid field data type.");
                    }

                    // Strip "Array" from field type.
                    fieldType = (PacketPackedFieldType)(((byte)fieldType) & ~((int)PacketPackedFieldType.Array));

                    // Read in array.
                    Type elementType        = realFieldType.GetElementType();
                    int arrayDimensions     = reader.ReadByte();
                    Array array            = null;
                    int[] arrayLengths      = new int[arrayDimensions];
                    int[] arrayLowerBounds  = new int[arrayDimensions];

                    // Read in array lengths.
                    for (int l = 0; l < arrayDimensions; l++)
                    {
                        arrayLengths[l] = reader.ReadInt32();
                        arrayLowerBounds[l] = 0;
                    }

                    // Create the array.
                    array = Array.CreateInstance(elementType, arrayLengths, arrayLowerBounds);

                    if (fieldType == PacketPackedFieldType.Null)
                    {
                        array = null;
                    }
                    else if (fieldType == PacketPackedFieldType.String)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(string))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            if (reader.ReadBoolean() == true)
                            {
                                array.SetValue(reader.ReadString(), val.Indicies);
                            }
                            else
                            {
                                array.SetValue(null, val.Indicies);
                            }
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Byte)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(byte))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadByte(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.UShort)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(ushort))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadUInt16(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Short)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(short))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadInt16(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.UInt)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(uint))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadUInt32(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Bool)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(bool))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadBoolean(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Int)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(int))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadInt32(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.ULong)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(ulong))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadUInt64(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Long)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(long))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadInt64(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Float)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(float))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadSingle(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Double)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(double))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadDouble(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Struct)
                    {
                        // Is field correct data type.
                        if (elementType.IsValueType != true && elementType.IsClass != true)
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            if (reader.ReadBoolean() == true)
                            {
                                object structResult = Activator.CreateInstance(elementType);//FormatterServices.GetUninitializedObject(realFieldType);
                                UnPackObjectFields(reader, structResult);
                                array.SetValue(structResult, val.Indicies);
                            }
                            else
                            {
                                array.SetValue(null, val.Indicies);
                            }
                        }
                    }
                    else
                    {
                        throw new FormatException("Packet contains invalid field data type.");
                    }

                    // Set the field value.
                    field.SetValue(obj, array);
                }
                else
                {
                    if (fieldType == PacketPackedFieldType.Null)
                    {
                        // Is field correct data type.
                        if (realFieldType.IsByRef == false && realFieldType.IsValueType == false && realFieldType.IsClass == false)
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, null);
                    }
                    else if (fieldType == PacketPackedFieldType.String)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(string))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadString());
                    }
                    else if (fieldType == PacketPackedFieldType.Byte)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(byte))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadByte());
                    }
                    else if (fieldType == PacketPackedFieldType.UShort)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(ushort))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadUInt16());
                    }
                    else if (fieldType == PacketPackedFieldType.Short)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(short))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadInt16());
                    }
                    else if (fieldType == PacketPackedFieldType.UInt)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(uint))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadUInt32());
                    }
                    else if (fieldType == PacketPackedFieldType.Bool)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(bool))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadBoolean());
                    }
                    else if (fieldType == PacketPackedFieldType.Int)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(int))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadInt32());
                    }
                    else if (fieldType == PacketPackedFieldType.ULong)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(ulong))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadUInt64());
                    }
                    else if (fieldType == PacketPackedFieldType.Long)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(long))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadInt64());
                    }
                    else if (fieldType == PacketPackedFieldType.Float)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(float))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadSingle());
                    }
                    else if (fieldType == PacketPackedFieldType.Double)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(double))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadDouble());
                    }
                    else if (fieldType == PacketPackedFieldType.Struct)
                    {
                        // Is field correct data type.
                        if (realFieldType.IsValueType != true && realFieldType.IsClass != true)
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        object structResult = null;
                        if (reader.ReadBoolean() == true)
                        {
                            structResult = Activator.CreateInstance(realFieldType); //FormatterServices.GetUninitializedObject(realFieldType); //
                            UnPackObjectFields(reader, structResult);
                        }
                        field.SetValue(obj, structResult);
                    }
                    else
                    {
                        throw new FormatException("Packet contains invalid field data type.");
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        ///     Serializes the fields of an object into a binary writer.
        /// </summary>
        /// <param name="writer">Writer to pack fields into.</param>
        /// <param name="obj">Object to pack fields of.</param>
        private void PackObjectFields(BinaryWriter writer, object obj)
        {
            // Write in field values.
            FieldInfo[] properties = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            // Order fields by names in alphabetical order.
            properties = properties.OrderBy(j => j.Name).ToArray();

            // Write number of fields.
            if (properties.Length >= 255)
            {
                throw new IndexOutOfRangeException("Packet can only have a maximum of 255 public fields.");
            }
            writer.Write((byte)properties.Length);

            // Write in hash code of fields.
            PearsonHash hash = new PearsonHash();
            foreach (FieldInfo field in properties)
            {
                byte[] bytes = StringHelper.StringToByteArray(field.Name);
                hash.AddBuffer(bytes, 0, bytes.Length);
            }
            writer.Write((byte)hash.Calculate());

            // Write in the fields!
            foreach (FieldInfo field in properties)
            {
                Type fieldType    = field.FieldType;
                object fieldValue = field.GetValue(obj);

                // Null.
                if (fieldValue == null)
                {
                    writer.Write((byte)PacketPackedFieldType.Null);
                }

                // String.
                else if (fieldType == typeof(string))
                {
                    writer.Write((byte)PacketPackedFieldType.String);
                    writer.Write((string)fieldValue);
                }

                // Integer types.
                else if (fieldType == typeof(byte))
                {
                    writer.Write((byte)PacketPackedFieldType.Byte);
                    writer.Write((byte)fieldValue);
                }
                else if (fieldType == typeof(ushort))
                {
                    writer.Write((byte)PacketPackedFieldType.UShort);
                    writer.Write((ushort)fieldValue);
                }
                else if (fieldType == typeof(short))
                {
                    writer.Write((byte)PacketPackedFieldType.Short);
                    writer.Write((short)fieldValue);
                }
                else if (fieldType == typeof(uint))
                {
                    writer.Write((byte)PacketPackedFieldType.UInt);
                    writer.Write((uint)fieldValue);
                }
                else if (fieldType == typeof(int))
                {
                    writer.Write((byte)PacketPackedFieldType.Int);
                    writer.Write((int)fieldValue);
                }
                else if (fieldType == typeof(bool))
                {
                    writer.Write((byte)PacketPackedFieldType.Bool);
                    writer.Write((bool)fieldValue);
                }
                else if (fieldType == typeof(ulong))
                {
                    writer.Write((byte)PacketPackedFieldType.ULong);
                    writer.Write((ulong)fieldValue);
                }
                else if (fieldType == typeof(long))
                {
                    writer.Write((byte)PacketPackedFieldType.Long);
                    writer.Write((long)fieldValue);
                }

                // Floating point types.
                else if (fieldType == typeof(float))
                {
                    writer.Write((byte)PacketPackedFieldType.Float);
                    writer.Write((float)fieldValue);
                }
                else if (fieldType == typeof(double))
                {
                    writer.Write((byte)PacketPackedFieldType.Double);
                    writer.Write((double)fieldValue);
                }

                // Other types of data.
                else
                {
                    // An array.
                    if (fieldType.IsArray)
                    {
                        Array array      = ((Array)fieldValue);
                        Type elementType = fieldType.GetElementType();

                        // Null
                        if (array == null)
                        {
                            writer.Write((byte)(PacketPackedFieldType.Null | PacketPackedFieldType.Array));
                            writer.Write((byte)0);
                        }

                        // String.
                        else if (elementType == typeof(string))
                        {
                            writer.Write((byte)(PacketPackedFieldType.String | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write(val.Value != null);
                                if (val.Value != null)
                                {
                                    writer.Write((string)val.Value);
                                }
                            }
                        }

                        // Integer types.
                        else if (elementType == typeof(byte))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Byte | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((byte)val.Value);
                            }
                        }
                        else if (elementType == typeof(ushort))
                        {
                            writer.Write((byte)(PacketPackedFieldType.UShort | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((ushort)val.Value);
                            }
                        }
                        else if (elementType == typeof(short))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Short | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((short)val.Value);
                            }
                        }
                        else if (elementType == typeof(uint))
                        {
                            writer.Write((byte)(PacketPackedFieldType.UInt | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((uint)val.Value);
                            }
                        }
                        else if (elementType == typeof(bool))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Bool | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((bool)val.Value);
                            }
                        }
                        else if (elementType == typeof(int))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Int | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((int)val.Value);
                            }
                        }
                        else if (elementType == typeof(ulong))
                        {
                            writer.Write((byte)(PacketPackedFieldType.ULong | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((ulong)val.Value);
                            }
                        }
                        else if (elementType == typeof(long))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Long | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((long)val.Value);
                            }
                        }

                        // Floating point types.
                        else if (elementType == typeof(float))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Float | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((float)val.Value);
                            }
                        }
                        else if (elementType == typeof(double))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Double | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((double)val.Value);
                            }
                        }

                        // Structs maybe?
                        else if (elementType.IsValueType == true || elementType.IsClass == true)
                        {
                            writer.Write((byte)(PacketPackedFieldType.Struct | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write(val.Value != null);
                                if (val.Value != null)
                                {
                                    PackObjectFields(writer, val.Value);
                                }
                            }
                        }

                        // Invalid data type.
                        else
                        {
                            throw new IndexOutOfRangeException("Packet contains an invalid data type for packing '" + elementType.Name + "'.");
                        }
                    }

                    // Structs maybe?
                    else if (fieldType.IsValueType == true || fieldType.IsClass == true)
                    {
                        writer.Write((byte)PacketPackedFieldType.Struct);
                        writer.Write(fieldValue != null);
                        PackObjectFields(writer, fieldValue);
                    }

                    // Invalid data type.
                    else
                    {
                        throw new IndexOutOfRangeException("Packet contains an invalid data type for packing '" + fieldType.Name + "'.");
                    }
                }
            }
        }