/// <summary>
        /// Encode literal header field according to Section 6.2.
        /// </summary>
        /// <param name="output">Output.</param>
        /// <param name="name">Name.</param>
        /// <param name="value">Value.</param>
        /// <param name="indexType">Index type.</param>
        /// <param name="nameIndex">Name index.</param>
        private void EncodeLiteral(BinaryWriter output, byte[] name, byte[] value, HPackUtil.IndexType indexType, int nameIndex)
        {
            int mask;
            int prefixBits;

            switch (indexType)
            {
            case HPackUtil.IndexType.INCREMENTAL:
                mask       = 0x40;
                prefixBits = 6;
                break;

            case HPackUtil.IndexType.NONE:
                mask       = 0x00;
                prefixBits = 4;
                break;

            case HPackUtil.IndexType.NEVER:
                mask       = 0x10;
                prefixBits = 4;
                break;

            default:
                throw new Exception("should not reach here");
            }
            Encoder.EncodeInteger(output, mask, prefixBits, nameIndex == -1 ? 0 : nameIndex);
            if (nameIndex == -1)
            {
                this.EncodeStringLiteral(output, name);
            }
            this.EncodeStringLiteral(output, value);
        }
 /// <summary>
 /// Set the maximum table size.
 /// </summary>
 /// <param name="output">Output.</param>
 /// <param name="maxHeaderTableSize">Max header table size.</param>
 public void SetMaxHeaderTableSize(BinaryWriter output, int maxHeaderTableSize)
 {
     if (maxHeaderTableSize < 0)
     {
         throw new ArgumentException("Illegal Capacity: " + maxHeaderTableSize);
     }
     if (this.capacity == maxHeaderTableSize)
     {
         return;
     }
     this.capacity = maxHeaderTableSize;
     this.EnsureCapacity(0);
     Encoder.EncodeInteger(output, 0x20, 5, maxHeaderTableSize);
 }
        /// <summary>
        /// Encode string literal according to Section 5.2.
        /// </summary>
        /// <param name="output">Output.</param>
        /// <param name="stringLiteral">String literal.</param>
        private void EncodeStringLiteral(BinaryWriter output, byte[] stringLiteral)
        {
            int huffmanLength = Huffman.ENCODER.GetEncodedLength(stringLiteral);

            if ((huffmanLength < stringLiteral.Length && !forceHuffmanOff) || forceHuffmanOn)
            {
                Encoder.EncodeInteger(output, 0x80, 7, huffmanLength);
                Huffman.ENCODER.Encode(output, stringLiteral);
            }
            else
            {
                Encoder.EncodeInteger(output, 0x00, 7, stringLiteral.Length);
                output.Write(stringLiteral, 0, stringLiteral.Length);
            }
        }
        /// <summary>
        /// Encode the header field into the header block.
        /// </summary>
        /// <param name="output">Output.</param>
        /// <param name="name">Name.</param>
        /// <param name="value">Value.</param>
        /// <param name="sensitive">If set to <c>true</c> sensitive.</param>
        public void EncodeHeader(BinaryWriter output, byte[] name, byte[] value, bool sensitive)
        {
            // If the header value is sensitive then it must never be indexed
            if (sensitive)
            {
                int nameIndex = this.GetNameIndex(name);
                this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NEVER, nameIndex);
                return;
            }

            // If the peer will only use the static table
            if (this.capacity == 0)
            {
                int staticTableIndex = StaticTable.GetIndex(name, value);
                if (staticTableIndex == -1)
                {
                    int nameIndex = StaticTable.GetIndex(name);
                    this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NONE, nameIndex);
                }
                else
                {
                    Encoder.EncodeInteger(output, 0x80, 7, staticTableIndex);
                }
                return;
            }

            int headerSize = HeaderField.SizeOf(name, value);

            // If the headerSize is greater than the max table size then it must be encoded literally
            if (headerSize > this.capacity)
            {
                int nameIndex = this.GetNameIndex(name);
                this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NONE, nameIndex);
                return;
            }

            HeaderEntry headerField = this.GetEntry(name, value);

            if (headerField != null)
            {
                int index = this.GetIndex(headerField.Index) + StaticTable.Length;
                // Section 6.1. Indexed Header Field Representation
                Encoder.EncodeInteger(output, 0x80, 7, index);
            }
            else
            {
                int staticTableIndex = StaticTable.GetIndex(name, value);
                if (staticTableIndex != -1)
                {
                    // Section 6.1. Indexed Header Field Representation
                    Encoder.EncodeInteger(output, 0x80, 7, staticTableIndex);
                }
                else
                {
                    int nameIndex = this.GetNameIndex(name);
                    if (useIndexing)
                    {
                        this.EnsureCapacity(headerSize);
                    }
                    var indexType = useIndexing ? HPackUtil.IndexType.INCREMENTAL : HPackUtil.IndexType.NONE;
                    this.EncodeLiteral(output, name, value, indexType, nameIndex);
                    if (useIndexing)
                    {
                        this.Add(name, value);
                    }
                }
            }
        }