/// <summary>
        /// Serialize fields to a stream.
        /// </summary>
        /// <param name="stream">The stream where serialized instance will be wrote.</param>
        /// <returns>Bytes written to the stream.</returns>
        public override int Serialize(Stream stream)
        {
            int bytesWriren = 0;

            this.stream = stream;
            this.deserializedcommandList = null;
            this.stack                 = new CommonByteStack();
            this.globcntRangeList      = GetGLOBCNTRange(this.GLOBCNTList);
            this.isAllGLOBCNTInGLOBSET = true;
            this.isAllGLOBCNTRanged    = true;
            this.isDisjointGLOBCNTMadeIntoSingleton = true;
            this.hasAllDuplicateGLOBCNTRemoved      = true;
            this.hasGLOBCNTGroupedIntoRanges        = true;
            bytesWriren += this.Compress(0, this.globcntRangeList.Count - 1);
            bytesWriren += this.End(stream);
            return(bytesWriren);
        }
        /// <summary>
        /// Deserialize fields in this class from a stream.
        /// </summary>
        /// <param name="stream">Stream contains a serialized instance of this class.</param>
        /// <param name="size">How many bytes can read if -1, no limitation.MUST be -1.</param>
        /// <returns>Bytes have been read from the stream.</returns>
        public override int Deserialize(Stream stream, int size)
        {
            AdapterHelper.Site.Assert.AreEqual(-1, size, "The size value MUST be -1, but the actual value is {0}.", size);

            int bytesRead = 0;

            this.stream                  = stream;
            this.globcntList             = new List <GLOBCNT>();
            this.globcntRangeList        = new List <GLOBCNTRange>();
            this.stack                   = new CommonByteStack();
            this.deserializedcommandList = new List <Command>();
            Operation op = this.ReadOperation();

            bytesRead += 1;
            while (op != Operation.End)
            {
                switch (op)
                {
                case Operation.Bitmask:
                    if (this.stack.Bytes != 5)
                    {
                        AdapterHelper.Site.Assert.Fail("The deserialization operation should be successful.");
                    }
                    else
                    {
                        byte[] commonBytes = stack.GetCommonBytes();
                        byte   startValue, bitmask;
                        bytesRead += ReadBitmaskValue(out startValue, out bitmask);
                        List <GLOBCNTRange> tmp   = FromBitmask(commonBytes, startValue, bitmask);
                        BitmaskCommand      bmCmd =
                            new BitmaskCommand((byte)op, startValue, bitmask)
                        {
                            CorrespondingGLOBCNTRangeList = tmp
                        };
                        deserializedcommandList.Add(bmCmd);
                        for (int i = 0; i < tmp.Count; i++)
                        {
                            globcntRangeList.Add(tmp[i]);
                        }

                        tmp = null;
                    }

                    break;

                case Operation.End:
                    this.deserializedcommandList.Add(new EndCommand((byte)op));
                    return(bytesRead);

                case Operation.Pop:
                    this.deserializedcommandList.Add(new PopCommand((byte)op));
                    this.stack.Pop();
                    break;

                case Operation.Range:
                {
                    byte[] lowValue, highValue;
                    bytesRead += this.ReadRangeValue(out lowValue, out highValue);
                    GLOBCNTRange range = this.FromRange(
                        this.stack.GetCommonBytes(),
                        lowValue,
                        highValue);
                    List <GLOBCNTRange> rangeList = new List <GLOBCNTRange>
                    {
                        range
                    };
                    RangeCommand rngCmd =
                        new RangeCommand((byte)op, lowValue, highValue)
                    {
                        CorrespondingGLOBCNTRangeList = rangeList
                    };

                    this.deserializedcommandList.Add(rngCmd);
                    this.globcntRangeList.Add(range);
                }

                break;

                case Operation.Push1:
                case Operation.Push2:
                case Operation.Push3:
                case Operation.Push4:
                case Operation.Push5:
                case Operation.Push6:
                    int    pushByteCount = (int)op;
                    byte[] pushBytes;
                    bytesRead += this.ReadPushedValue(pushByteCount, out pushBytes);
                    PushCommand pshCmd = new PushCommand((byte)op, pushBytes);
                    if (6 == pushByteCount + this.stack.Bytes)
                    {
                        List <GLOBCNTRange> rangeList = new List <GLOBCNTRange>();
                        GLOBCNTRange        range     = this.FromPush(this.stack.GetCommonBytes(), pushBytes);
                        rangeList.Add(range);
                        this.globcntRangeList.Add(range);
                        pshCmd.CorrespondingGLOBCNTRangeList = rangeList;
                        this.deserializedcommandList.Add(pshCmd);
                        break;
                    }

                    this.deserializedcommandList.Add(pshCmd);
                    this.stack.Push(pushBytes);
                    break;

                default:
                    AdapterHelper.Site.Assert.Fail("The operation get from the stream is invalid, its value is {0}.", op);
                    break;
                }

                op         = this.ReadOperation();
                bytesRead += 1;
            }

            if (op == Operation.End)
            {
                this.deserializedcommandList.Add(new EndCommand((byte)op));
            }

            this.isAllGLOBCNTInGLOBSET = true;
            this.isAllGLOBCNTRanged    = true;
            this.isDisjointGLOBCNTMadeIntoSingleton = true;
            this.hasAllDuplicateGLOBCNTRemoved      = true;
            this.hasGLOBCNTGroupedIntoRanges        = true;
            return(bytesRead);
        }