/// <summary>
        /// Remove and return the oldest header field from the dynamic table.
        /// </summary>
        private HeaderField Remove()
        {
            if (this.size == 0)
            {
                return(null);
            }
            HeaderEntry eldest = head.After;
            int         h      = eldest.Hash;
            int         i      = Encoder.Index(h);
            HeaderEntry prev   = headerFields[i];
            HeaderEntry e      = prev;

            while (e != null)
            {
                HeaderEntry next = e.Next;
                if (e == eldest)
                {
                    if (prev == eldest)
                    {
                        headerFields[i] = next;
                    }
                    else
                    {
                        prev.Next = next;
                    }
                    eldest.Remove();
                    this.size -= eldest.Size;
                    return(eldest);
                }
                prev = e;
                e    = next;
            }
            return(null);
        }
        /// <summary>
        /// Add the header field to the dynamic table.
        /// Entries are evicted from the dynamic table until the size of the table
        /// and the new header field is less than the table's capacity.
        /// If the size of the new entry is larger than the table's capacity,
        /// the dynamic table will be cleared.
        /// </summary>
        /// <param name="name">Name.</param>
        /// <param name="value">Value.</param>
        private void Add(byte[] name, byte[] value)
        {
            int headerSize = HeaderField.SizeOf(name, value);

            // Clear the table if the header field size is larger than the capacity.
            if (headerSize > this.capacity)
            {
                this.Clear();
                return;
            }

            // Evict oldest entries until we have enough capacity.
            while (this.size + headerSize > this.capacity)
            {
                this.Remove();
            }

            // Copy name and value that modifications of original do not affect the dynamic table.
            name.CopyTo(name, 0);
            value.CopyTo(value, 0);

            int         h   = Encoder.Hash(name);
            int         i   = Encoder.Index(h);
            HeaderEntry old = headerFields[i];
            HeaderEntry e   = new HeaderEntry(h, name, value, head.Before.Index - 1, old);

            headerFields[i] = e;
            e.AddBefore(head);
            this.size += headerSize;
        }
        /// <summary>
        /// Returns the header entry with the lowest index value for the header field.
        /// Returns null if header field is not in the dynamic table.
        /// </summary>
        /// <returns>The entry.</returns>
        /// <param name="name">Name.</param>
        /// <param name="value">Value.</param>
        private HeaderEntry GetEntry(byte[] name, byte[] value)
        {
            if (this.Length() == 0 || name == null || value == null)
            {
                return(null);
            }
            int h = Encoder.Hash(name);
            int i = Encoder.Index(h);

            for (HeaderEntry e = headerFields[i]; e != null; e = e.Next)
            {
                if (e.Hash == h && HPackUtil.Equals(name, e.Name) && HPackUtil.Equals(value, e.Value))
                {
                    return(e);
                }
            }
            return(null);
        }
        /// <summary>
        /// Returns the lowest index value for the header field name in the dynamic table.
        /// Returns -1 if the header field name is not in the dynamic table.
        /// </summary>
        /// <returns>The index.</returns>
        /// <param name="name">Name.</param>
        private int GetIndex(byte[] name)
        {
            if (this.Length() == 0 || name == null)
            {
                return(-1);
            }
            int h     = Encoder.Hash(name);
            int i     = Encoder.Index(h);
            int index = -1;

            for (HeaderEntry e = headerFields[i]; e != null; e = e.Next)
            {
                if (e.Hash == h && HPackUtil.Equals(name, e.Name))
                {
                    index = e.Index;
                    break;
                }
            }
            return(this.GetIndex(index));
        }