/// <summary>
        /// Reads data from an STDF data stream and deserializes it into the corresponding STDF record type.
        /// </summary>
        /// <param name="stream">Stream object to read the record data from.</param>
        /// <returns></returns>
        public override object Deserialize(Stream stream)
        {
            SerializeStream = stream;
            EndOfStream     = SerializeStream.Position >= SerializeStream.Length;
            if (EndOfStream)
            {
                return(null);
            }
            ReadHeader(out ushort recordLength, out ushort recordTypeCode);
            if (SerializeStream.Position + recordLength > SerializeStream.Length)
            {
                throw new EndOfStreamException("Unexpected end of record during serialization.");
            }
            Type       recordType          = STDFFormatterServices.ConvertTypeCode(recordTypeCode);
            ISurrogate serializerSurrogate = TypeSurrogateSelector.GetSurrogate(recordType);

            if (serializerSurrogate == null)
            {
                // no surrogate to deserialize this type.  Skip to next record and return
                SerializeStream.Seek(recordLength, SeekOrigin.Current);
                //Console.WriteLine("Skipping record type " + recordType.Name);
                return(null);
            }
            ISTDFRecord record = (ISTDFRecord)STDFFormatterServices.GetUninitializedObject(recordType);

            record.RecordLength = recordLength;
            SerializationInfo info = SerializationInfo.Create(recordType, Converter);
            long startPosition     = SerializeStream.Position;

            foreach (SerializationInfoEntry field in info)
            {
                EndOfRecord = (SerializeStream.Position - startPosition) >= recordLength;
                if (EndOfRecord)
                {
                    // If end of record reached yet we still have more fields to serialize, then we can skip the rest of the record.
                    break;
                }
                if (field.ItemCountIndex >= 0)
                {
                    // Field has an item count property, so we are deserializing an array.
                    // Get the number of items to deserialize from the value that was deserialized earlier.
                    int itemCount = info.GetValue <int>((int)field.ItemCountIndex);
                    if (itemCount > 0)
                    {
                        info.SetValue(field.Index, ReadArray(field.Type.GetElementType(), itemCount));
                    }
                }
                else
                {
                    info.SetValue(field.Index, Read(field.Type));
                }
            }
            EndOfStream = SerializeStream.Position >= SerializeStream.Length;
            // Set the fields on the record
            serializerSurrogate.SetObjectData(record, info);
            return(record);
        }
        /// <summary>
        /// Serializes and STDF record object to the output stream.
        /// </summary>
        /// <param name="stream">Stream object to serialized the STDF data to.</param>
        /// <param name="obj">STDF record object to serialize.</param>
        public override void Serialize(Stream stream, object obj)
        {
            Buffer.SetLength(0);
            SerializeStream = Buffer;
            EndOfStream     = false;
            EndOfRecord     = false;
            ushort recordLength = 0;

            if (obj is ISTDFRecord record)
            {
                ISurrogate typeSurrogate = TypeSurrogateSelector.GetSurrogate(record.GetType());
                if (typeSurrogate == null)
                {
                    return;
                }
                //WriteHeader(0, record.RecordType);
                //                long recordStartPosition = SerializeStream.Position;
                Type recordType        = record.GetType();
                SerializationInfo info = SerializationInfo.Create(recordType, Converter);
                typeSurrogate.GetObjectData(record, info);
                foreach (SerializationInfoEntry field in info)
                {
                    if (field.ItemCountIndex >= 0)
                    {
                        // field has an item count property, so we are serializing an array.  Get the number of items
                        // to serialize from the item count field serialized earlier (we always serialize according
                        // to the item count field rather than the array size for the array field.  Normally these are
                        // equal but it is not mandatory that they be equal).
                        int itemCount = field.ItemCountIndex != null?info.GetValue <int>((int)field.ItemCountIndex) : 0;

                        if (itemCount > 0)
                        {
                            WriteArray(field.Value, field.Type.GetElementType(), 0, itemCount);
                        }
                    }
                    else
                    {
                        WriteMember(field.Value, field.Type);
                    }
                    // For optional fields, save the position after the last field written
                    // that does not have a missing value.  Per spec, we can truncate any contiguous missing
                    // value fields from the end of the record.
                    if (!field.IsMissingValue)
                    {
                        recordLength = (ushort)(SerializeStream.Position);
                    }
                }
                //recordLength = (ushort)(lastValidPosition - recordStartPosition);
                if (recordLength != record.RecordLength)
                {
                    throw new Exception("Mismatched record length.");
                }
                record.RecordLength = recordLength;
                //SerializeStream.Seek(-(SerializeStream.Position - recordStartPosition + 4), SeekOrigin.Current);
                SerializeStream.Flush();
                SerializeStream = stream;
                WriteHeader(record.RecordLength, record.RecordType);
                //                SerializeStream.Seek(record.RecordLength, SeekOrigin.Current);
                //                SerializeStream.SetLength(SerializeStream.Position);
                Buffer.SetLength(recordLength);
                Buffer.WriteTo(stream);
                EndOfRecord = true;
            }
        }