class HTTP2::Header::Decompressor

Responsible for decoding received headers and maintaining compression context of the opposing peer. Decompressor must be initialized with appropriate starting context based on local role: client or server.

@example

server_role = Decompressor.new(:request)
client_role = Decompressor.new(:response)

Public Class Methods

new(**options) click to toggle source

@param options [Hash] decoding options. Only :table_size is effective.

# File lib/http/2/compressor.rb, line 467
def initialize(**options)
  @cc = EncodingContext.new(options)
end

Public Instance Methods

decode(buf) click to toggle source

Decodes and processes header commands within provided buffer.

@param buf [Buffer] @return [Array] +[[name, value], …]+

# File lib/http/2/compressor.rb, line 550
def decode(buf)
  list = []
  list << @cc.process(header(buf)) until buf.empty?
  list.compact
end
header(buf) click to toggle source

Decodes header command from provided buffer.

@param buf [Buffer] @return [Hash] command

# File lib/http/2/compressor.rb, line 515
def header(buf)
  peek = buf.readbyte(0)

  header = {}
  header[:type], type = HEADREP.find do |_t, desc|
    mask = (peek >> desc[:prefix]) << desc[:prefix]
    mask == desc[:pattern]
  end

  fail CompressionError unless header[:type]

  header[:name] = integer(buf, type[:prefix])

  case header[:type]
  when :indexed
    fail CompressionError if header[:name] == 0
    header[:name] -= 1
  when :changetablesize
    header[:value] = header[:name]
  else
    if header[:name] == 0
      header[:name] = string(buf)
    else
      header[:name] -= 1
    end
    header[:value] = string(buf)
  end

  header
end
integer(buf, n) click to toggle source

Decodes integer value from provided buffer.

@param buf [String] @param n [Integer] number of available bits @return [Integer]

# File lib/http/2/compressor.rb, line 482
def integer(buf, n)
  limit = 2**n - 1
  i = !n.zero? ? (buf.getbyte & limit) : 0

  m = 0
  while (byte = buf.getbyte)
    i += ((byte & 127) << m)
    m += 7

    break if (byte & 128).zero?
  end if (i == limit)

  i
end
string(buf) click to toggle source

Decodes string value from provided buffer.

@param buf [String] @return [String] UTF-8 encoded string @raise [CompressionError] when input is malformed

# File lib/http/2/compressor.rb, line 502
def string(buf)
  huffman = (buf.readbyte(0) & 0x80) == 0x80
  len = integer(buf, 7)
  str = buf.read(len)
  fail CompressionError, 'string too short' unless str.bytesize == len
  str = Huffman.new.decode(Buffer.new(str)) if huffman
  str.force_encoding(Encoding::UTF_8)
end
table_size=(size) click to toggle source

Set dynamic table size in EncodingContext @param size [Integer] new dynamic table size

# File lib/http/2/compressor.rb, line 473
def table_size=(size)
  @cc.table_size = size
end