// **********************************************************************************************************
//    serializationSupport.cs
//    6/1/2022
//    NGI - Next Generation Interceptor
//    
//    Contract No. HQ0856-21-C-0003/1022000209
//    
//    THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S. 
//    INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//    
//    RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON 
//    COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. 
//    DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON 
//    COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED 
//    TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF 
//    RAYTHEON COMPANY.
//    
//    UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//    
//    DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M, 
//    NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006, 
//    INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3, 
//    DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3, 
//    SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4, 
//    INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//    
//    CONTROLLED BY: MISSILE DEFENSE AGENCY
//    CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
//    CUI CATEGORY: CTI 
//    DISTRIBUTION/DISSEMINATION CONTROL: F 
//    POC: Alex Kravchenko (1118268)
// **********************************************************************************************************

//\\<Unclassified>
//----------------------------------------------------------------------------//
//                                 UNCLASSIFIED                               //
//----------------------------------------------------------------------------//
//\\<\Unclassified>

//\\<UnlimitedRights>
//----------------------------------------------------------------------------//
// Copyright %(copyright)s Raytheon Company.                                  //
// This software was developed pursuant to Contract Number %(contractNumber)s //
// with the U.S. government. The U.S. government's rights in and to this      //
// copyrighted software are as specified in DFARS 252.227-7014 which was made //
// part of the above contract.                                                //
//----------------------------------------------------------------------------//
//\\<\UnlimitedRights>

//\\<EximUndetermined>
//----------------------------------------------------------------------------//
// WARNING - This document contains technical data and / or technology whose  //
// export or disclosure to Non-U.S. Persons, wherever located, is restricted  //
// by the International Traffic in Arms Regulations (ITAR) (22 C.F.R.         //
// Section 120-130) or the Export Administration Regulations (EAR) (15 C.F.R. //
// Section 730-774). This document CANNOT be exported (e.g., provided to a    //
// supplier outside of the United States) or disclosed to a Non-U.S. Person,  //
// wherever located, until a final jurisdiction and classification            //
// determination has been completed and approved by Raytheon, and any         //
// required U.S. Government approvals have been obtained. Violations are      //
// subject to severe criminal penalties.                                      //
//----------------------------------------------------------------------------//
//\\<\EximUndetermined>

using System;
using System.Reflection;

namespace Raytheon.Instruments.coeCSharp
{
    //
    //
    //
    // Serialization Support
    //
    //
    //
    public class serializationSupport
    {
        public static int getPayloadSize(object target, Type targetType, ref int size)
        {
            FieldInfo[] fields = targetType.GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                getFieldSize(field, target, ref size);
            }
            return size;
        }
        public static int getFieldSize(FieldInfo field, object target, ref int size)
        {
            if (field.FieldType == typeof(char) ||
                 field.FieldType == typeof(byte) ||
                 field.FieldType == typeof(byte) ||
                 field.FieldType == typeof(sbyte))
            {
                size += 1;
            }
            else if (field.FieldType == typeof(char[]) ||
                     field.FieldType == typeof(byte[]) ||
                     field.FieldType == typeof(byte[]) ||
                     field.FieldType == typeof(sbyte[]))
            {
                byte[] values = (byte[])field.GetValue(target);
                size += 1 * ((Array)field.GetValue(target)).Length;
            }
            else if (field.FieldType == typeof(short) ||
                     field.FieldType == typeof(ushort) ||
                     field.FieldType == typeof(short) ||
                     field.FieldType == typeof(ushort))
            {
                alignIndex(ref size, 2);
                size += 2;
            }
            else if (field.FieldType == typeof(short[]) ||
                     field.FieldType == typeof(ushort[]) ||
                     field.FieldType == typeof(short[]) ||
                     field.FieldType == typeof(ushort[]))
            {
                alignIndex(ref size, 2);
                size += 2 * ((Array)field.GetValue(target)).Length;
            }
            else if (field.FieldType == typeof(int) ||
                     field.FieldType == typeof(uint) ||
                     field.FieldType == typeof(int) ||
                     field.FieldType == typeof(uint) ||
                     field.FieldType == typeof(float))
            {
                alignIndex(ref size, 4);
                size += 4;
            }
            else if (field.FieldType == typeof(int[]) ||
                     field.FieldType == typeof(uint[]) ||
                     field.FieldType == typeof(int[]) ||
                     field.FieldType == typeof(uint[]) ||
                     field.FieldType == typeof(float[]))
            {
                alignIndex(ref size, 4);
                size += 4 * ((Array)field.GetValue(target)).Length;
            }
            else if (field.FieldType == typeof(long) ||
                     field.FieldType == typeof(ulong) ||
                     field.FieldType == typeof(long) ||
                     field.FieldType == typeof(ulong) ||
                     field.FieldType == typeof(double))
            {
                alignIndex(ref size, 8);
                size += 8;
            }
            else if (field.FieldType == typeof(long[]) ||
                     field.FieldType == typeof(ulong[]) ||
                     field.FieldType == typeof(long[]) ||
                     field.FieldType == typeof(ulong[]) ||
                     field.FieldType == typeof(double[]))
            {
                alignIndex(ref size, 8);
                size += 8 * ((Array)field.GetValue(target)).Length;
            }
            else if (field.FieldType.IsArray) // Array of classes
            {
                alignIndex(ref size, 4);
                Array targetArray = (Array)field.GetValue(target);
                int arraySize = targetArray.Length;
                object[] objectArray = (object[])field.GetValue(target);
                var arrayElementType = objectArray.GetType().GetElementType();
                for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
                {
                    object arrayItem = objectArray[arrayIndex];
                    Type arrayItemType = arrayItem.GetType();
                    FieldInfo[] subfields = arrayItemType.GetFields(BindingFlags.Public | BindingFlags.Instance);
                    foreach (FieldInfo subfield in subfields)
                    {
                        Type subfieldType = subfield.GetType();
                        Type elementType = subfield.FieldType.GetElementType();
                        getFieldSize(subfield, arrayItem, ref size);
                    }
                }
            }
            else // Class
            {
                alignIndex(ref size, 4);
                object objectItem = field.GetValue(target);
                FieldInfo[] subfields = field.FieldType.GetFields(BindingFlags.Public | BindingFlags.Instance);
                foreach (FieldInfo subfield in subfields)
                {
                    Type subfieldType = subfield.GetType();
                    Type elementType = subfield.FieldType.GetElementType();
                    getFieldSize(subfield, objectItem, ref size);
                }
            }
            return size;
        }

        public static void alignIndex(ref int dataBufferIndex, int alignment)
        {
            int indexMisalignment = dataBufferIndex % alignment;
            if (indexMisalignment > 0)
            {
                dataBufferIndex += alignment - indexMisalignment;
            }
        }
        public static void serializeField(FieldInfo field,
                                          byte[] dataBuffer,
                                          ref int dataBufferIndex,
                                          object target)
        {
            Type fieldType = field.GetType();
            object fieldObject = field.GetValue(target);

            if (field.FieldType == typeof(char) ||
                field.FieldType == typeof(byte) ||
                field.FieldType == typeof(byte) ||
                field.FieldType == typeof(sbyte))
            {
                byte value = Convert.ToByte(field.GetValue(target));
                dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
            }
            else if (field.FieldType == typeof(char[]))
            {
                char[] values = (char[])field.GetValue(target);
                foreach (char value in values)
                {
                    dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                }
            }
            else if (field.FieldType == typeof(byte[]) ||
                     field.FieldType == typeof(byte[]) ||
                     field.FieldType == typeof(sbyte[]))
            {
                byte[] values = (byte[])field.GetValue(target);
                foreach (byte value in values)
                {
                    dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                }
            }
            else if (field.FieldType == typeof(short) ||
                     field.FieldType == typeof(ushort) ||
                     field.FieldType == typeof(short) ||
                     field.FieldType == typeof(ushort))
            {
                alignIndex(ref dataBufferIndex, 2);
                ushort value = Convert.ToUInt16(field.GetValue(target));
                dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 8 & 0xFF);
            }
            else if (field.FieldType == typeof(short[]) ||
                     field.FieldType == typeof(ushort[]) ||
                     field.FieldType == typeof(short[]) ||
                     field.FieldType == typeof(ushort[]))
            {
                alignIndex(ref dataBufferIndex, 2);
                ushort[] values = (ushort[])field.GetValue(target);
                foreach (char value in values)
                {
                    dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 8 & 0xFF);
                }
            }
            else if (field.FieldType == typeof(int) ||
                     field.FieldType == typeof(uint) ||
                     field.FieldType == typeof(int) ||
                     field.FieldType == typeof(uint))
            {
                alignIndex(ref dataBufferIndex, 4);
                uint value = Convert.ToUInt32(field.GetValue(target));
                dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 8 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 16 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 24 & 0xFF);
            }
            else if (field.FieldType == typeof(float))
            {
                alignIndex(ref dataBufferIndex, 4);
                float floatValue = (float)field.GetValue(target);
                byte[] valueArray = BitConverter.GetBytes(floatValue);
                dataBuffer[dataBufferIndex++] = valueArray[0];
                dataBuffer[dataBufferIndex++] = valueArray[1];
                dataBuffer[dataBufferIndex++] = valueArray[2];
                dataBuffer[dataBufferIndex++] = valueArray[3];
            }
            else if (field.FieldType == typeof(int[]) ||
                     field.FieldType == typeof(uint[]) ||
                     field.FieldType == typeof(int[]) ||
                     field.FieldType == typeof(uint[]))
            {
                alignIndex(ref dataBufferIndex, 4);
                uint[] values = (uint[])field.GetValue(target);
                foreach (uint value in values)
                {
                    dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 8 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 16 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 24 & 0xFF);
                }
            }
            else if (field.FieldType == typeof(float[]))
            {
                alignIndex(ref dataBufferIndex, 4);
                float[] values = (float[])field.GetValue(target);
                foreach (float floatValue in values)
                {
                    byte[] valueArray = BitConverter.GetBytes(floatValue);
                    dataBuffer[dataBufferIndex++] = valueArray[0];
                    dataBuffer[dataBufferIndex++] = valueArray[1];
                    dataBuffer[dataBufferIndex++] = valueArray[2];
                    dataBuffer[dataBufferIndex++] = valueArray[3];
                }
            }
            else if (field.FieldType == typeof(long) ||
                     field.FieldType == typeof(ulong) ||
                     field.FieldType == typeof(long) ||
                     field.FieldType == typeof(ulong))
            {
                alignIndex(ref dataBufferIndex, 8);
                ulong value = Convert.ToUInt64(field.GetValue(target));
                dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 8 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 16 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 24 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 32 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 40 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 48 & 0xFF);
                dataBuffer[dataBufferIndex++] = (byte)(value >> 56 & 0xFF);
            }
            else if (field.FieldType == typeof(double))
            {
                alignIndex(ref dataBufferIndex, 8);
                double doubleValue = (double)field.GetValue(target);
                byte[] valueArray = BitConverter.GetBytes(doubleValue);
                dataBuffer[dataBufferIndex++] = valueArray[0];
                dataBuffer[dataBufferIndex++] = valueArray[1];
                dataBuffer[dataBufferIndex++] = valueArray[2];
                dataBuffer[dataBufferIndex++] = valueArray[3];
                dataBuffer[dataBufferIndex++] = valueArray[4];
                dataBuffer[dataBufferIndex++] = valueArray[5];
                dataBuffer[dataBufferIndex++] = valueArray[6];
                dataBuffer[dataBufferIndex++] = valueArray[7];
            }
            else if (field.FieldType == typeof(long[]) ||
                     field.FieldType == typeof(ulong[]) ||
                     field.FieldType == typeof(long[]) ||
                     field.FieldType == typeof(ulong[]))
            {
                alignIndex(ref dataBufferIndex, 8);
                ulong[] values = (ulong[])field.GetValue(target);
                foreach (ulong value in values)
                {
                    dataBuffer[dataBufferIndex++] = (byte)(value & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 8 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 16 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 24 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 32 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 40 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 48 & 0xFF);
                    dataBuffer[dataBufferIndex++] = (byte)(value >> 56 & 0xFF);
                }
            }
            else if (field.FieldType == typeof(double[]))
            {
                alignIndex(ref dataBufferIndex, 8);
                double[] values = (double[])field.GetValue(target);
                foreach (double doubleValue in values)
                {
                    byte[] valueArray = BitConverter.GetBytes(doubleValue);
                    dataBuffer[dataBufferIndex++] = valueArray[0];
                    dataBuffer[dataBufferIndex++] = valueArray[1];
                    dataBuffer[dataBufferIndex++] = valueArray[2];
                    dataBuffer[dataBufferIndex++] = valueArray[3];
                    dataBuffer[dataBufferIndex++] = valueArray[4];
                    dataBuffer[dataBufferIndex++] = valueArray[5];
                    dataBuffer[dataBufferIndex++] = valueArray[6];
                    dataBuffer[dataBufferIndex++] = valueArray[7];
                }
            }
            else if (field.FieldType.IsArray) // Array of classes
            {
                alignIndex(ref dataBufferIndex, 4);
                Array targetArray = (Array)field.GetValue(target);
                int arraySize = targetArray.Length;
                object[] objectArray = (object[])field.GetValue(target);
                Type arrayElementType = objectArray.GetType().GetElementType();
                for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
                {
                    object arrayItem = objectArray[arrayIndex];
                    Type arrayItemType = arrayItem.GetType();
                    FieldInfo[] subfields = arrayItemType.GetFields(BindingFlags.Public | BindingFlags.Instance);
                    foreach (FieldInfo subfield in subfields)
                    {
                        Type subfieldType = subfield.GetType();
                        Type elementType = subfield.FieldType.GetElementType();
                        serializeField(subfield, dataBuffer, ref dataBufferIndex, arrayItem);
                    }
                }
            }
            else  // Class
            {
                alignIndex(ref dataBufferIndex, 4);
                FieldInfo[] subfields = fieldObject.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
                foreach (FieldInfo subfield in subfields)
                {
                    Type subfieldType = subfield.GetType();
                    Type elementType = subfield.FieldType.GetElementType();
                    serializeField(subfield, dataBuffer, ref dataBufferIndex, fieldObject);
                }
            }
        }

        public static void deserializeField(FieldInfo field,
                                            byte[] dataBuffer,
                                            ref int dataBufferIndex,
                                            object target)
        {
            Type fieldType = field.GetType();
            object fieldObject = field.GetValue(target);

            if (field.FieldType == typeof(char))
            {
                char value = Convert.ToChar(dataBuffer[dataBufferIndex++]);
                field.SetValue(target, value);
            }
            else if (field.FieldType == typeof(byte) ||
                     field.FieldType == typeof(byte))
            {
                byte value = dataBuffer[dataBufferIndex++];
                field.SetValue(target, value);
            }
            else if (field.FieldType == typeof(sbyte))
            {
                sbyte value = Convert.ToSByte(dataBuffer[dataBufferIndex++]);
                field.SetValue(target, value);
            }
            else if (field.FieldType == typeof(char[]))
            {
                char[] values = (char[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = (char)dataBuffer[dataBufferIndex++];
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType == typeof(byte[]) ||
                     field.FieldType == typeof(byte[]))
            {
                byte[] values = (byte[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = dataBuffer[dataBufferIndex++];
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType == typeof(sbyte[]))
            {
                sbyte[] values = (sbyte[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = (sbyte)dataBuffer[dataBufferIndex++];
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType == typeof(short) ||
                     field.FieldType == typeof(ushort) ||
                     field.FieldType == typeof(short) ||
                     field.FieldType == typeof(ushort))
            {
                alignIndex(ref dataBufferIndex, 2);
                ushort value = (ushort)(dataBuffer[dataBufferIndex++] +
                               (ushort)(dataBuffer[dataBufferIndex++] << 8));
                if (field.FieldType == typeof(short) ||
                    field.FieldType == typeof(short))
                {
                    field.SetValue(target, Convert.ToInt16(value));
                }
                else
                {
                    field.SetValue(target, value);
                }
            }
            else if (field.FieldType == typeof(short[]) ||
                     field.FieldType == typeof(ushort[]) ||
                     field.FieldType == typeof(short[]) ||
                     field.FieldType == typeof(ushort[]))
            {
                alignIndex(ref dataBufferIndex, 2);
                ushort[] values = (ushort[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = (ushort)(dataBuffer[dataBufferIndex++] +
                                    (ushort)(dataBuffer[dataBufferIndex++] << 8));
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType == typeof(int) ||
                     field.FieldType == typeof(uint) ||
                     field.FieldType == typeof(int) ||
                     field.FieldType == typeof(uint))
            {
                alignIndex(ref dataBufferIndex, 4);
                uint value = dataBuffer[dataBufferIndex++] +
                               ((uint)dataBuffer[dataBufferIndex++] << 8) +
                               ((uint)dataBuffer[dataBufferIndex++] << 16) +
                               ((uint)dataBuffer[dataBufferIndex++] << 24);
                if (field.FieldType == typeof(int) ||
                    field.FieldType == typeof(int))
                {
                    field.SetValue(target, Convert.ToInt32(value));
                }
                else
                {
                    field.SetValue(target, value);
                }
            }
            else if (field.FieldType == typeof(int[]) ||
                     field.FieldType == typeof(uint[]) ||
                     field.FieldType == typeof(int[]) ||
                     field.FieldType == typeof(uint[]))
            {
                alignIndex(ref dataBufferIndex, 4);
                uint[] values = (uint[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = dataBuffer[dataBufferIndex++] +
                                    ((uint)dataBuffer[dataBufferIndex++] << 8) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 16) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 24);
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType == typeof(float))
            {
                alignIndex(ref dataBufferIndex, 4);
                float singleValue = BitConverter.ToSingle(dataBuffer, dataBufferIndex);
                dataBufferIndex += 4;
                field.SetValue(target, singleValue);
            }
            else if (field.FieldType == typeof(float[]))
            {
                alignIndex(ref dataBufferIndex, 4);
                float[] values = (float[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = BitConverter.ToSingle(dataBuffer, dataBufferIndex);
                    dataBufferIndex += 4;
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType == typeof(long) ||
                     field.FieldType == typeof(ulong) ||
                     field.FieldType == typeof(long) ||
                     field.FieldType == typeof(ulong))
            {
                alignIndex(ref dataBufferIndex, 8);
                uint value = dataBuffer[dataBufferIndex++] +
                               ((uint)dataBuffer[dataBufferIndex++] << 8) +
                               ((uint)dataBuffer[dataBufferIndex++] << 16) +
                               ((uint)dataBuffer[dataBufferIndex++] << 24) +
                               ((uint)dataBuffer[dataBufferIndex++] << 32) +
                               ((uint)dataBuffer[dataBufferIndex++] << 40) +
                               ((uint)dataBuffer[dataBufferIndex++] << 48) +
                               ((uint)dataBuffer[dataBufferIndex++] << 56);
                if (field.FieldType == typeof(long) ||
                    field.FieldType == typeof(long))
                {
                    field.SetValue(target, Convert.ToInt64(value));
                }
                else
                {
                    field.SetValue(target, value);
                }
            }
            else if (field.FieldType == typeof(long[]) ||
                     field.FieldType == typeof(ulong[]) ||
                     field.FieldType == typeof(long[]) ||
                     field.FieldType == typeof(ulong[]))
            {
                alignIndex(ref dataBufferIndex, 8);
                ulong[] values = (ulong[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = dataBuffer[dataBufferIndex++] +
                                    ((uint)dataBuffer[dataBufferIndex++] << 8) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 16) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 24) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 32) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 40) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 48) +
                                    ((uint)dataBuffer[dataBufferIndex++] << 56);
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType == typeof(double))
            {
                alignIndex(ref dataBufferIndex, 8);
                field.SetValue(target, BitConverter.ToDouble(dataBuffer, dataBufferIndex));
                dataBufferIndex += 8;
            }
            else if (field.FieldType == typeof(double[]))
            {
                alignIndex(ref dataBufferIndex, 8);
                double[] values = (double[])field.GetValue(target);
                for (int index = 0; index < values.Length; index++)
                {
                    values[index] = BitConverter.ToDouble(dataBuffer, dataBufferIndex);
                    dataBufferIndex += 8;
                }
                field.SetValue(target, values);
            }
            else if (field.FieldType.IsArray)
            {
                alignIndex(ref dataBufferIndex, 4);
                Array targetArray = (Array)field.GetValue(target);
                int arraySize = targetArray.Length;
                object[] objectArray = (object[])field.GetValue(target);
                Type arrayElementType = objectArray.GetType().GetElementType();
                for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
                {
                    object arrayItem = objectArray[arrayIndex];
                    Type arrayItemType = arrayItem.GetType();
                    FieldInfo[] subfields = arrayItemType.GetFields(BindingFlags.Public | BindingFlags.Instance);
                    foreach (FieldInfo subfield in subfields)
                    {
                        Type subfieldType = subfield.GetType();
                        Type elementType = subfield.FieldType.GetElementType();
                        deserializeField(subfield, dataBuffer, ref dataBufferIndex, arrayItem);
                    }
                }
            }
            else
            {
                alignIndex(ref dataBufferIndex, 4);
                FieldInfo[] subfields = fieldObject.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
                foreach (FieldInfo subfield in subfields)
                {
                    Type subfieldType = subfield.GetType();
                    object subfieldObject = subfield.GetValue(fieldObject);
                    Type elementType = subfield.FieldType.GetElementType();
                    deserializeField(subfield, dataBuffer, ref dataBufferIndex, fieldObject);
                }
            }
        }

    }
}

//\\<Unclassified>
//----------------------------------------------------------------------------//
//                                 UNCLASSIFIED                               //
//----------------------------------------------------------------------------//
//\\<\Unclassified>

