/// <summary> /// Compress incremental. /// </summary> /// <param name="header">The header.</param> private void CompressIncremental(KeyValuePair <string, string> header) { const byte prefix = (byte)UVarIntPrefix.Incremental; /* 12 -> 8.1.3 * Just as in HTTP/1.x, header field names are strings of ASCII * characters that are compared in a case-insensitive fashion. However, * header field names MUST be converted to lowercase prior to their * encoding in HTTP/2. */ int index = _remoteHeadersTable.FindIndex(kv => kv.Key.Equals(header.Key, StringComparison.OrdinalIgnoreCase)); bool isFound = index != -1; /* 07 -> 3.1.4 * <---------- Index Address Space ----------> * <-- Header Table --> <-- Static Table --> +---+-----------+---+ +---+-----------+---+ | 1 | ... | k | |k+1| ... | n | +---+-----------+---+ +---+-----------+---+ | ^ | | V | Insertion Point Drop Point */ // It's necessary to form result array because partial writeToOutput stream // can cause problems because of multithreading using (var stream = new MemoryStream(64)) { byte[] indexBinary; byte[] nameBinary = new byte[0]; byte[] valueBinary; if (isFound) { // Header key was found in the header table. Hence we should encode only value indexBinary = (index + 1).ToUVarInt(prefix); valueBinary = EncodeString(header.Value, true); } else { // Header key was not found in the header table. Hence we should encode name and value indexBinary = 0.ToUVarInt(prefix); nameBinary = EncodeString(header.Key, true); valueBinary = EncodeString(header.Value, true); } // Set without index type indexBinary[0] |= (byte)IndexationType.Incremental; stream.Write(indexBinary, 0, indexBinary.Length); stream.Write(nameBinary, 0, nameBinary.Length); stream.Write(valueBinary, 0, valueBinary.Length); WriteToOutput(stream.GetBuffer(), 0, (int)stream.Position); } InsertToHeadersTable(header, _remoteRefSet, _remoteHeadersTable); }