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
@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
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
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
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
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
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