/// <summary>
        /// Create an encoder with the target initial buffer size.
        /// </summary>
        /// <param name="compress">True to compress collated data.</param>
        /// <param name="initialBufferSize">The initial buffer size (bytes).</param>
        public CollatedPacketEncoder(bool compress, int initialBufferSize = 64 * 1024)
        {
            CollatedBytes    = 0;
            _collationStream = _dataStream = new CompressionBuffer(initialBufferSize);
            _packet          = new PacketBuffer();

            // Prime the output stream, writing the initial header.
            PacketHeader header = PacketHeader.Create((ushort)RoutingID.CollatedPacket, 0);

            CollatedPacketMessage msg = new CollatedPacketMessage();

            msg.Flags             = (ushort)((compress) ? CollatedPacketFlag.GZipCompressed : 0u);
            msg.Reserved          = 0;
            msg.UncompressedBytes = 0;

            NetworkWriter writer = new NetworkWriter(_dataStream);

            header.Write(writer);
            msg.Write(writer);

            _resetPosition = (int)_dataStream.Position;

            CompressionEnabled = compress;
            if (compress)
            {
                _collationStream = new GZipStream(_dataStream, CompressionMode.Compress, CompressionLevel.BestCompression);
            }
        }
        /// <summary>
        /// Finalise the collated packet before sending.
        /// </summary>
        /// <returns>True on successful finalisation, false if already finalised</returns>
        public bool FinaliseEncoding()
        {
            if (_finalised)
            {
                return(false);
            }

            bool compressionSuccess = false;

            if (CompressionEnabled)
            {
                // Compress the raw buffer into the compression buffer then validate it's smaller.
                _finalisedBuffer.Position = 0;

                // First write the standard header for this buffer.
                // Prime the output stream, writing the initial header.
                PacketHeader header = PacketHeader.Create((ushort)RoutingID.CollatedPacket, 0);

                CollatedPacketMessage msg = new CollatedPacketMessage();
                msg.Flags             = (ushort)CollatedPacketFlag.GZipCompressed;
                msg.Reserved          = 0;
                msg.UncompressedBytes = 0;

                NetworkWriter writer = new NetworkWriter(_finalisedBuffer);
                header.Write(writer);
                msg.Write(writer);

                int overhead = (int)_finalisedBuffer.Position;

                // Now compress the collated packets.
                GZipStream compressionStream = new GZipStream(_finalisedBuffer, CompressionLevel.Fastest);
                compressionStream.Write(_collationBuffer.GetBuffer(), 0, (int)_collationBuffer.Position);
                compressionStream.Close();
                if (_finalisedBuffer.Position < _collationBuffer.Position + overhead)
                {
                    // The compressed data are smaller, so we accept it.
                    SetPayloadSize((ushort)(Count - PacketHeader.Size));
                    // Update the payload and uncompressed sizes.
                    SetUncompressedBytesSize((ushort)CollatedBytes);
                    compressionSuccess = true;
                }
            }

            if (!compressionSuccess)
            {
                // No compression or compression failed to reduce the data size. Write header then copy wrap packets.
                PacketHeader header = PacketHeader.Create((ushort)RoutingID.CollatedPacket, 0);

                _finalisedBuffer.Position = 0;

                CollatedPacketMessage msg = new CollatedPacketMessage();
                msg.Flags             = 0;
                msg.Reserved          = 0;
                msg.UncompressedBytes = 0;

                NetworkWriter writer = new NetworkWriter(_finalisedBuffer);
                header.Write(writer);
                msg.Write(writer);

                _finalisedBuffer.Write(_collationBuffer.GetBuffer(), 0, (int)_collationBuffer.Position);
                // The compressed data are smaller, so we accept it.
                SetPayloadSize((ushort)(Count - PacketHeader.Size));
                // Update the payload and uncompressed sizes.
                SetUncompressedBytesSize((ushort)CollatedBytes);
            }

            // Calculate the CRC
            ushort crc = Crc16.Crc.Calculate(_finalisedBuffer.GetBuffer(), (uint)_finalisedBuffer.Position);

            new NetworkWriter(_finalisedBuffer).Write(crc);
            _finalised = true;
            return(true);
        }