This class specifies the base class for 16-bit or 32-bit stream object header start.
Inheritance: BasicObject
        /// <summary>
        /// This method is used to deserialize the items of the cell knowledge from the byte array.
        /// </summary>
        /// <param name="byteArray">Specify the byte array.</param>
        /// <param name="currentIndex">Specify the start index from the byte array.</param>
        /// <param name="lengthOfItems">Specify the current length of items in the cell knowledge.</param>
        protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems)
        {
            if (lengthOfItems != 0)
            {
                throw new KnowledgeParseErrorException(currentIndex, "CellKnowledge object over-parse error", null);
            }

            int index = currentIndex;
            StreamObjectHeaderStart header;
            int length = 0;

            this.CellKnowledgeEntryList = new List <CellKnowledgeEntry>();
            this.CellKnowledgeRangeList = new List <CellKnowledgeRange>();
            while ((length = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0)
            {
                index += length;
                if (header.Type == StreamObjectTypeHeaderStart.CellKnowledgeEntry)
                {
                    this.CellKnowledgeEntryList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as CellKnowledgeEntry);
                }
                else if (header.Type == StreamObjectTypeHeaderStart.CellKnowledgeRange)
                {
                    this.CellKnowledgeRangeList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as CellKnowledgeRange);
                }
                else
                {
                    throw new KnowledgeParseErrorException(currentIndex, "Failed to parse CellKnowledge, expect the inner object type is either CellKnowledgeEntry or CellKnowledgeRange but actual type value is " + header.Type, null);
                }
            }

            currentIndex = index;
        }
Exemple #2
0
        /// <summary>
        /// Used to de-serialize the element.
        /// </summary>
        /// <param name="byteArray">A Byte array</param>
        /// <param name="currentIndex">Start position</param>
        /// <param name="lengthOfItems">The length of the items</param>
        protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems)
        {
            int index = currentIndex;

            if (lengthOfItems != 0)
            {
                throw new StreamObjectParseErrorException(currentIndex, "LeafNodeObjectData", "Stream Object over-parse error", null);
            }

            this.Signature = StreamObject.GetCurrent <SignatureObject>(byteArray, ref index);
            this.DataSize  = StreamObject.GetCurrent <DataSizeObject>(byteArray, ref index);

            // Try to read StreamObjectHeaderStart to see there is data hash object or not
            StreamObjectHeaderStart streamObjectHeader;

            if ((StreamObjectHeaderStart.TryParse(byteArray, index, out streamObjectHeader)) != 0)
            {
                if (streamObjectHeader.Type == StreamObjectTypeHeaderStart.DataHashObject)
                {
                    this.DataHash = StreamObject.GetCurrent <DataHashObject>(byteArray, ref index);
                }
            }

            currentIndex = index;
        }
        /// <summary>
        /// This method is used to parse the actual 16bit or 32bit stream header.
        /// </summary>
        /// <param name="byteArray">Specify the Byte array.</param>
        /// <param name="startIndex">Specify the start position.</param>
        /// <param name="streamObjectHeader">Specify the out value for the parse result.</param>
        /// <returns>Return true if success, otherwise returns false. </returns>
        public static int TryParse(byte[] byteArray, int startIndex, out StreamObjectHeaderStart streamObjectHeader)
        {
            uint headerType = (uint)(byteArray[startIndex] & 0x3);
            if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart16bit)
            {
                streamObjectHeader = new StreamObjectHeaderStart16bit();
            }
            else
            {
                if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart32bit)
                {
                    streamObjectHeader = new StreamObjectHeaderStart32bit();
                }
                else
                {
                    streamObjectHeader = null;
                    return 0;
                }
            }

            try
            {
                return streamObjectHeader.DeserializeFromByteArray(byteArray, startIndex);
            }
            catch (InvalidOperationException)
            {
                streamObjectHeader = null;
                return 0;
            }
        }
        /// <summary>
        /// This method is used to parse the actual 16bit or 32bit stream header.
        /// </summary>
        /// <param name="byteArray">Specify the Byte array.</param>
        /// <param name="startIndex">Specify the start position.</param>
        /// <param name="streamObjectHeader">Specify the out value for the parse result.</param>
        /// <returns>Return true if success, otherwise returns false. </returns>
        public static int TryParse(byte[] byteArray, int startIndex, out StreamObjectHeaderStart streamObjectHeader)
        {
            uint headerType = (uint)(byteArray[startIndex] & 0x3);

            if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart16bit)
            {
                streamObjectHeader = new StreamObjectHeaderStart16bit();
            }
            else
            {
                if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart32bit)
                {
                    streamObjectHeader = new StreamObjectHeaderStart32bit();
                }
                else
                {
                    streamObjectHeader = null;
                    return(0);
                }
            }

            try
            {
                return(streamObjectHeader.DeserializeFromByteArray(byteArray, startIndex));
            }
            catch (InvalidOperationException)
            {
                streamObjectHeader = null;
                return(0);
            }
        }
        /// <summary>
        /// Deserialize sub response data from byte array.
        /// </summary>
        /// <param name="byteArray">The byte array which contains sub response data.</param>
        /// <param name="currentIndex">The index special where to start.</param>
        protected override void DeserializeSubResponseDataFromByteArray(byte[] byteArray, ref int currentIndex)
        {
            int index = currentIndex;

            int headerLength = 0;
            StreamObjectHeaderStart header;

            if ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) == 0)
            {
                throw new ResponseParseErrorException(index, "Failed to parse the AllocateExtendedGuidRangeData stream object header", null);
            }

            if (header.Type != StreamObjectTypeHeaderStart.AllocateExtendedGUIDRangeResponse)
            {
                throw new ResponseParseErrorException(index, "Failed to extract the AllocateExtendedGuidRangeData stream object header type, unexpected value " + header.Type, null);
            }

            this.AllocateExtendedGUIDRangeResponse = new StreamObjectHeaderStart32bit(header.Type, header.Length);
            index += headerLength;
            int currentTmpIndex = index;

            byte[] guidarray = new byte[16];
            Array.Copy(byteArray, index, guidarray, 0, 16);
            this.GUIDComponent = new Guid(guidarray);
            index += 16;
            this.IntegerRangeMin = BasicObject.Parse <Compact64bitInt>(byteArray, ref index);
            this.IntegerRangeMax = BasicObject.Parse <Compact64bitInt>(byteArray, ref index);

            if (index - currentTmpIndex != header.Length)
            {
                throw new ResponseParseErrorException(-1, "AllocateExtendedGuidRangeData object over-parse error", null);
            }

            currentIndex = index;
        }
Exemple #6
0
        /// <summary>
        /// Try to get current object, true will returned if success.
        /// </summary>
        /// <typeparam name="T">The type of target object.</typeparam>
        /// <param name="byteArray">The byte array.</param>
        /// <param name="index">The position where to start.</param>
        /// <param name="streamObject">The instance that want to get.</param>
        /// <returns>The result of whether get success.</returns>
        public static bool TryGetCurrent <T>(byte[] byteArray, ref int index, out T streamObject)
            where T : StreamObject
        {
            int tmpIndex = index;

            streamObject = null;

            int length = 0;
            StreamObjectHeaderStart streamObjectHeader;

            if ((length = StreamObjectHeaderStart.TryParse(byteArray, tmpIndex, out streamObjectHeader)) == 0)
            {
                return(false);
            }

            tmpIndex += length;
            if (StreamObjectTypeMapping.Keys.Contains(streamObjectHeader.Type) && StreamObjectTypeMapping[streamObjectHeader.Type] == typeof(T))
            {
                streamObject = ParseStreamObject(streamObjectHeader, byteArray, ref tmpIndex) as T;
            }
            else
            {
                return(false);
            }

            index = tmpIndex;
            return(true);
        }
Exemple #7
0
        /// <summary>
        /// Get current stream object.
        /// </summary>
        /// <typeparam name="T">The type of target object.</typeparam>
        /// <param name="byteArray">The byte array which contains message.</param>
        /// <param name="index">The position where to start.</param>
        /// <returns>The current object instance.</returns>
        public static T GetCurrent <T>(byte[] byteArray, ref int index)
            where T : StreamObject
        {
            int tmpIndex = index;
            int length   = 0;
            StreamObjectHeaderStart streamObjectHeader;

            if ((length = StreamObjectHeaderStart.TryParse(byteArray, tmpIndex, out streamObjectHeader)) == 0)
            {
                throw new StreamObjectParseErrorException(tmpIndex, typeof(T).Name, "Failed to extract either 16bit or 32bit stream object header in the current index.", null);
            }

            tmpIndex += length;

            StreamObject streamObject = ParseStreamObject(streamObjectHeader, byteArray, ref tmpIndex);

            if (!(streamObject is T))
            {
                throw new StreamObjectParseErrorException(tmpIndex, typeof(T).Name, string.Format("Failed to get stream object as expect type {0}, actual type is {1}", typeof(T).Name, StreamObjectTypeMapping[streamObjectHeader.Type].Name), null);
            }

            // Store the current index to the ref parameter index.
            index = tmpIndex;
            return(streamObject as T);
        }
Exemple #8
0
        /// <summary>
        /// Used to de-serialize data element.
        /// </summary>
        /// <param name="byteArray">Byte array</param>
        /// <param name="startIndex">Start position</param>
        /// <returns>The length of the array</returns>
        public override int DeserializeDataElementDataFromByteArray(byte[] byteArray, int startIndex)
        {
            int index = startIndex;

            this.StorageManifestSchemaGUID      = StreamObject.GetCurrent <StorageManifestSchemaGUID>(byteArray, ref index);
            this.StorageManifestRootDeclareList = new List <StorageManifestRootDeclare>();

            StreamObjectHeaderStart header;
            int headerLength = 0;

            while ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0)
            {
                if (header.Type == StreamObjectTypeHeaderStart.StorageManifestRootDeclare)
                {
                    index += headerLength;
                    this.StorageManifestRootDeclareList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageManifestRootDeclare);
                }
                else
                {
                    throw new DataElementParseErrorException(index, "Failed to parse StorageManifestDataElement, expect the inner object type StorageManifestRootDeclare, but actual type value is " + header.Type, null);
                }
            }

            return(index - startIndex);
        }
        /// <summary>
        /// Used to de-serialize the element.
        /// </summary>
        /// <param name="byteArray">A Byte array</param>
        /// <param name="currentIndex">Start position</param>
        /// <param name="lengthOfItems">The length of the items</param>
        protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems)
        {
            if (lengthOfItems != 0)
            {
                throw new StreamObjectParseErrorException(currentIndex, "ObjectGroupMetadataDeclarations", "Stream object over-parse error", null);
            }

            int index        = currentIndex;
            int headerLength = 0;
            StreamObjectHeaderStart header;

            this.ObjectGroupMetadataList = new List <ObjectGroupMetadata>();

            while ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0)
            {
                index += headerLength;
                if (header.Type == StreamObjectTypeHeaderStart.ObjectGroupMetadata)
                {
                    this.ObjectGroupMetadataList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as ObjectGroupMetadata);
                }
                else
                {
                    throw new StreamObjectParseErrorException(index, "ObjectGroupDeclarations", "Failed to parse ObjectGroupMetadataDeclarations, expect the inner object type ObjectGroupMetadata, but actual type value is " + header.Type, null);
                }
            }

            currentIndex = index;
        }
        /// <summary>
        /// This method is used to deserialize the items of the specialized knowledge from the byte array.
        /// </summary>
        /// <param name="byteArray">Specify the byte array.</param>
        /// <param name="currentIndex">Specify the start index from the byte array.</param>
        /// <param name="lengthOfItems">Specify the current length of items in the specialized knowledge.</param>
        protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems)
        {
            if (lengthOfItems != 16)
            {
                throw new KnowledgeParseErrorException(currentIndex, "Failed to check the stream object header length in the DeserializeSpecializedKnowledgeFromByteArray", null);
            }

            int index = currentIndex;

            byte[] temp = new byte[16];
            Array.Copy(byteArray, index, temp, 0, 16);
            this.GUID = new Guid(temp);
            if (!KnowledgeTypeGuidMapping.Keys.Contains(this.GUID))
            {
                throw new KnowledgeParseErrorException(index, string.Format("Failed to check the special knowledge guid value in the DeserializeSpecializedKnowledgeFromByteArray, the value {0 }is not defined", this.GUID), null);
            }

            index += 16;
            this.specializedKnowledgeData = Activator.CreateInstance(KnowledgeTypeGuidMapping[this.GUID]) as SpecializedKnowledgeData;

            StreamObjectHeaderStart specializedKnowledgeDataHeader;
            int headerLength = 0;

            if ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out specializedKnowledgeDataHeader)) == 0)
            {
                throw new KnowledgeParseErrorException(index, "Failed to parse the specialized knowledge data stream object header", null);
            }

            if (!KnowledgeEnumGuidMapping.Keys.Contains(specializedKnowledgeDataHeader.Type))
            {
                throw new KnowledgeParseErrorException(index, "Unexpected specialized knowledge data stream object header type " + specializedKnowledgeDataHeader.Type, null);
            }

            if (KnowledgeEnumGuidMapping[specializedKnowledgeDataHeader.Type] != this.GUID)
            {
                throw new KnowledgeParseErrorException(index, "Unmatched specialized knowledge data stream object header type and the specified guid value", null);
            }

            index += headerLength;
            try
            {
                index += this.specializedKnowledgeData.DeserializeFromByteArray(specializedKnowledgeDataHeader, byteArray, index);
            }
            catch (StreamObjectParseErrorException streamObjectException)
            {
                throw new KnowledgeParseErrorException(index, streamObjectException);
            }
            catch (BasicObjectParseErrorException basicObjectException)
            {
                throw new KnowledgeParseErrorException(index, basicObjectException);
            }

            currentIndex = index;
        }
Exemple #11
0
        /// <summary>
        /// Used to return the length of this element.
        /// </summary>
        /// <param name="header">Then instance of StreamObjectHeaderStart.</param>
        /// <param name="byteArray">The byte list</param>
        /// <param name="startIndex">The position where to start.</param>
        /// <returns>The element length</returns>
        public int DeserializeFromByteArray(StreamObjectHeaderStart header, byte[] byteArray, int startIndex)
        {
            this.StreamObjectType = header.Type;
            this.LengthOfItems    = header.Length;

            if (header is StreamObjectHeaderStart32bit)
            {
                if (header.Length == 32767)
                {
                    this.LengthOfItems = (int)(header as StreamObjectHeaderStart32bit).LargeLength.DecodedValue;
                }
            }

            int index = startIndex;

            this.StreamObjectHeaderStart = header;
            this.DeserializeItemsFromByteArray(byteArray, ref index, this.LengthOfItems);

            if (CompoundTypes.Contains(this.StreamObjectType))
            {
                StreamObjectHeaderEnd end       = null;
                BitReader             bitReader = new BitReader(byteArray, index);
                int aField = bitReader.ReadInt32(2);
                if (aField == 0x1)
                {
                    end = BasicObject.Parse <StreamObjectHeaderEnd8bit>(byteArray, ref index);
                }
                if (aField == 0x3)
                {
                    end = BasicObject.Parse <StreamObjectHeaderEnd16bit>(byteArray, ref index);
                }

                if ((int)end.Type != (int)this.StreamObjectType)
                {
                    throw new StreamObjectParseErrorException(index, null, "Unexpected the stream header end value " + (int)this.StreamObjectType, null);
                }

                this.StreamObjectHeaderEnd = end;
            }

            // Capture all the type related requirements
            if (SharedContext.Current.IsMsFsshttpRequirementsCaptured)
            {
                new MsfsshttpbAdapterCapture().InvokeCaptureMethod(this.GetType(), this, SharedContext.Current.Site);
            }

            return(index - startIndex);
        }
Exemple #12
0
        /// <summary>
        /// Parse stream object from byte array.
        /// </summary>
        /// <param name="header">The instance of StreamObjectHeaderStart.</param>
        /// <param name="byteArray">The byte array.</param>
        /// <param name="index">The position where to start.</param>
        /// <returns>The instance of StreamObject.</returns>
        public static StreamObject ParseStreamObject(StreamObjectHeaderStart header, byte[] byteArray, ref int index)
        {
            if (StreamObjectTypeMapping.Keys.Contains(header.Type))
            {
                StreamObject streamObject = Activator.CreateInstance(StreamObjectTypeMapping[header.Type]) as StreamObject;

                try
                {
                    index += streamObject.DeserializeFromByteArray(header, byteArray, index);
                }
                catch (BasicObjectParseErrorException e)
                {
                    throw new StreamObjectParseErrorException(index, StreamObjectTypeMapping[header.Type].Name, e);
                }

                return(streamObject);
            }

            int tmpIndex = index;

            tmpIndex -= header.HeaderType == StreamObjectHeaderStart.StreamObjectHeaderStart16bit ? 2 : 4;
            throw new StreamObjectParseErrorException(tmpIndex, "Unknown", string.Format("Failed to create the specified stream object instance, the type {0} of stream object header in the current index is not defined", (int)header.Type), null);
        }
Exemple #13
0
        /// <summary>
        /// Used to de-serialize the data element.
        /// </summary>
        /// <param name="byteArray">Byte array</param>
        /// <param name="startIndex">Start position</param>
        /// <returns>The length of the element</returns>
        public override int DeserializeDataElementDataFromByteArray(byte[] byteArray, int startIndex)
        {
            int index        = startIndex;
            int headerLength = 0;
            StreamObjectHeaderStart header;
            bool isStorageIndexManifestMappingExist = false;

            while ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0)
            {
                index += headerLength;
                if (header.Type == StreamObjectTypeHeaderStart.StorageIndexManifestMapping)
                {
                    if (isStorageIndexManifestMappingExist)
                    {
                        throw new DataElementParseErrorException(index - headerLength, "Failed to parse StorageIndexDataElement, only can contain zero or one StorageIndexManifestMapping", null);
                    }

                    this.StorageIndexManifestMapping   = StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageIndexManifestMapping;
                    isStorageIndexManifestMappingExist = true;
                }
                else if (header.Type == StreamObjectTypeHeaderStart.StorageIndexCellMapping)
                {
                    this.StorageIndexCellMappingList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageIndexCellMapping);
                }
                else if (header.Type == StreamObjectTypeHeaderStart.StorageIndexRevisionMapping)
                {
                    this.StorageIndexRevisionMappingList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageIndexRevisionMapping);
                }
                else
                {
                    throw new DataElementParseErrorException(index - headerLength, "Failed to parse StorageIndexDataElement, expect the inner object type StorageIndexCellMapping or StorageIndexRevisionMapping, but actual type value is " + header.Type, null);
                }
            }

            return(index - startIndex);
        }
        /// <summary>
        /// This method is used to convert the element into a byte List
        /// </summary>
        /// <returns>Return the Byte List</returns>
        public List <byte> SerializeToByteList()
        {
            this.RequestStart     = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.Request, 0);
            this.UserAgentStart   = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgent, 0);
            this.UserAgentGUID    = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentGUID, 16);
            this.UserAgentVersion = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentversion, 4);
            this.UserAgentEnd     = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.UserAgent);
            this.CellRequestEnd   = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.Request);

            List <byte> byteList = new List <byte>();

            // Protocol Version
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.ProtocolVersion));

            // Minimum Version
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.MinimumVersion));

            // Signature
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Signature));

            // Request Start
            byteList.AddRange(this.RequestStart.SerializeToByteList());

            // User Agent Start
            byteList.AddRange(this.UserAgentStart.SerializeToByteList());

            // User Agent GUID
            byteList.AddRange(this.UserAgentGUID.SerializeToByteList());

            // GUID
            byteList.AddRange(this.GUID.ToByteArray());

            // User Agent Version
            byteList.AddRange(this.UserAgentVersion.SerializeToByteList());

            // Version
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Version));

            // User Agent End
            byteList.AddRange(this.UserAgentEnd.SerializeToByteList());

            if (this.IsRequestHashingOptionsUsed)
            {
                List <byte> hashSchemaList = this.RequestHashingSchema.SerializeToByteList();
                this.RequestHashingOptionsDeclaration = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.RequestHashOptions, hashSchemaList.Count + 1);

                // Request Hashing Options Declaration
                byteList.AddRange(this.RequestHashingOptionsDeclaration.SerializeToByteList());

                // Request Hashing Schema
                byteList.AddRange(hashSchemaList);

                // Reserve
                BitWriter bw = new BitWriter(1);
                bw.AppendInit32(this.Reserve1, 1);
                bw.AppendInit32(this.Reserve2, 1);
                bw.AppendInit32(this.RequestDataElementHashesInsteadofData, 1);
                bw.AppendInit32(this.RequestDataElementHashes, 1);
                bw.AppendInit32(this.Reserve3, 4);
                byteList.AddRange(bw.Bytes);
            }

            // Sub-requests
            if (this.SubRequests != null && this.SubRequests.Count != 0)
            {
                foreach (FsshttpbCellSubRequest subRequest in this.SubRequests)
                {
                    byteList.AddRange(subRequest.SerializeToByteList());
                }
            }
            else
            {
                throw new InvalidOperationException("MUST contain sub request in request structure which is defined in the MS-FSSHTTPB.");
            }

            // Data Element Package
            if (this.DataElementPackage != null)
            {
                byteList.AddRange(this.DataElementPackage.SerializeToByteList());
            }

            // Cell Request End
            byteList.AddRange(this.CellRequestEnd.SerializeToByteList());

            return(byteList);
        }
        /// <summary>
        /// Deserialize response from byte array.
        /// </summary>
        /// <param name="byteArray">Server returned message.</param>
        /// <param name="startIndex">The index special where start.</param>
        /// <returns>The instance of CellResponse.</returns>
        public static FsshttpbResponse DeserializeResponseFromByteArray(byte[] byteArray, int startIndex)
        {
            int index = startIndex;

            FsshttpbResponse response = new FsshttpbResponse();

            response.ProtocolVersion = LittleEndianBitConverter.ToUInt16(byteArray, index);
            index += 2;

            response.MinimumVersion = LittleEndianBitConverter.ToUInt16(byteArray, index);
            index += 2;

            response.Signature = LittleEndianBitConverter.ToUInt64(byteArray, index);
            index += 8;

            int length = 0;
            StreamObjectHeaderStart streamObjectHeader;

            if ((length = StreamObjectHeaderStart.TryParse(byteArray, index, out streamObjectHeader)) == 0)
            {
                throw new ResponseParseErrorException(index, "Failed to parse the response header", null);
            }

            if (!(streamObjectHeader is StreamObjectHeaderStart32bit))
            {
                throw new ResponseParseErrorException(index, "Unexpected 16-bit response stream object header, expect 32-bit stream object header for Response", null);
            }

            if (streamObjectHeader.Type != StreamObjectTypeHeaderStart.FsshttpbResponse)
            {
                throw new ResponseParseErrorException(index, "Failed to extract the response header type, unexpected value " + streamObjectHeader.Type, null);
            }

            if (streamObjectHeader.Length != 1)
            {
                throw new ResponseParseErrorException(index, "Response object over-parse error", null);
            }

            index += length;
            response.ResponseStart = streamObjectHeader as StreamObjectHeaderStart32bit;

            response.Status   = (byteArray[index] & 0x1) == 0x1 ? true : false;
            response.Reserved = (byte)(byteArray[index] >> 1);
            index            += 1;

            try
            {
                if (response.Status)
                {
                    response.ResponseError      = StreamObject.GetCurrent <ResponseError>(byteArray, ref index);
                    response.DataElementPackage = null;
                    response.CellSubResponses   = null;
                }
                else
                {
                    DataElementPackage package;
                    if (StreamObject.TryGetCurrent <DataElementPackage>(byteArray, ref index, out package))
                    {
                        response.DataElementPackage = package;
                    }

                    response.CellSubResponses = new List <FsshttpbSubResponse>();
                    FsshttpbSubResponse subResponse;
                    while (StreamObject.TryGetCurrent <FsshttpbSubResponse>(byteArray, ref index, out subResponse))
                    {
                        response.CellSubResponses.Add(subResponse);
                    }
                }

                response.ResponseEnd = BasicObject.Parse <StreamObjectHeaderEnd16bit>(byteArray, ref index);
            }
            catch (StreamObjectParseErrorException streamObjectException)
            {
                throw new ResponseParseErrorException(index, streamObjectException);
            }
            catch (DataElementParseErrorException dataElementException)
            {
                throw new ResponseParseErrorException(index, dataElementException);
            }
            catch (KnowledgeParseErrorException knowledgeException)
            {
                throw new ResponseParseErrorException(index, knowledgeException);
            }

            if (index != byteArray.Length)
            {
                throw new ResponseParseErrorException(index, "Failed to pass the whole response, not reach the end of the byte array", null);
            }

            return(response);
        }
        /// <summary>
        /// This method is used to convert the element into a byte List 
        /// </summary>
        /// <returns>Return the Byte List</returns>
        public List<byte> SerializeToByteList()
        {
            this.RequestStart = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.Request, 0);
            this.UserAgentStart = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgent, 0);
            this.UserAgentGUID = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentGUID, 16);
            this.UserAgentVersion = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentversion, 4);
            this.UserAgentEnd = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.UserAgent);
            this.CellRequestEnd = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.Request);
            
            List<byte> byteList = new List<byte>();

            // Protocol Version
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.ProtocolVersion));

            // Minimum Version
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.MinimumVersion));

            // Signature
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Signature));

            // Request Start
            byteList.AddRange(this.RequestStart.SerializeToByteList());

            // User Agent Start
            byteList.AddRange(this.UserAgentStart.SerializeToByteList());

            // User Agent GUID
            byteList.AddRange(this.UserAgentGUID.SerializeToByteList());

            // GUID
            byteList.AddRange(this.GUID.ToByteArray());

            // User Agent Version
            byteList.AddRange(this.UserAgentVersion.SerializeToByteList());

            // Version
            byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Version));

            // User Agent End
            byteList.AddRange(this.UserAgentEnd.SerializeToByteList());

            if (this.IsRequestHashingOptionsUsed)
            {
                List<byte> hashSchemaList = this.RequestHashingSchema.SerializeToByteList();
                this.RequestHashingOptionsDeclaration = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.RequestHashOptions, hashSchemaList.Count + 1);

                // Request Hashing Options Declaration
                byteList.AddRange(this.RequestHashingOptionsDeclaration.SerializeToByteList());

                // Request Hashing Schema
                byteList.AddRange(hashSchemaList);

                // Reserve
                BitWriter bw = new BitWriter(1);
                bw.AppendInit32(this.Reserve1, 1);
                bw.AppendInit32(this.Reserve2, 1);
                bw.AppendInit32(this.RequestDataElementHashesInsteadofData, 1);
                bw.AppendInit32(this.RequestDataElementHashes, 1);
                bw.AppendInit32(this.Reserve3, 4);
                byteList.AddRange(bw.Bytes);
            }

            // Sub-requests
            if (this.SubRequests != null && this.SubRequests.Count != 0)
            {
                foreach (FsshttpbCellSubRequest subRequest in this.SubRequests)
                {
                    byteList.AddRange(subRequest.SerializeToByteList());
                }
            }
            else
            {
                throw new InvalidOperationException("MUST contain sub request in request structure which is defined in the MS-FSSHTTPB.");
            }

            // Data Element Package 
            if (this.DataElementPackage != null)
            {
                byteList.AddRange(this.DataElementPackage.SerializeToByteList());
            }

            // Cell Request End 
            byteList.AddRange(this.CellRequestEnd.SerializeToByteList());

            return byteList;
        }