lib/protocol/hpack/context.rb in protocol-hpack-1.1.0 vs lib/protocol/hpack/context.rb in protocol-hpack-1.2.0
- old
+ new
@@ -29,13 +29,13 @@
module HPACK
# Header representation as defined by the spec.
HEADER_REPRESENTATION = {
indexed: {prefix: 7, pattern: 0x80},
incremental: {prefix: 6, pattern: 0x40},
- noindex: {prefix: 4, pattern: 0x00},
- neverindexed: {prefix: 4, pattern: 0x10},
- changetablesize: {prefix: 5, pattern: 0x20},
+ no_index: {prefix: 4, pattern: 0x00},
+ never_indexed: {prefix: 4, pattern: 0x10},
+ change_table_size: {prefix: 5, pattern: 0x20},
}
# To decompress header blocks, a decoder only needs to maintain a
# dynamic table as a decoding context.
# No other state information is needed.
@@ -103,52 +103,42 @@
['transfer-encoding', ''],
['user-agent', ''],
['vary', ''],
['via', ''],
['www-authenticate', ''],
- ].each {|pair| pair.each(&:freeze).freeze}.freeze
-
- # Current table of header key-value pairs.
- attr_reader :table
-
- # Current encoding options
+ ].each {|pair| pair.each(&:freeze).freeze}.freeze
+
+ # Initializes compression context with appropriate client/server defaults and maximum size of the dynamic table.
#
- # :table_size Integer maximum dynamic table size in bytes
- # :huffman Symbol :always, :never, :shorter
- # :index Symbol :all, :static, :never
- attr_reader :options
-
- # Initializes compression context with appropriate client/server
- # defaults and maximum size of the dynamic table.
- #
- # @param options [Hash] encoding options
- # :table_size Integer maximum dynamic table size in bytes
- # :huffman Symbol :always, :never, :shorter
- # :index Symbol :all, :static, :never
- def initialize(**options)
- default_options = {
- huffman: :shorter,
- index: :all,
- table_size: 4096,
- }
+ # @param table [Array] Table of header key-value pairs.
+ # @option huffman [Symbol] One of `:always`, `:never`, `:shorter`. Controls use of compression.
+ # @option index [Symbol] One of `:all`, `:static`, `:never`. Controls use of static/dynamic tables.
+ # @option table_size [Integer] The current maximum dynamic table size.
+ def initialize(table = nil, huffman: :shorter, index: :all, table_size: 4096)
+ @huffman = huffman
+ @index = index
- @table = []
- @options = default_options.merge(options)
- @limit = @options[:table_size]
+ @table_size = table_size
+
+ @table = (table&.dup) || []
end
-
- # Duplicates current compression context
- # @return [Context]
- def dup
- other = Context.new(@options)
+
+ def initialize_copy(other)
+ super
- other.instance_variable_set :@table, @table.dup
- other.instance_variable_set :@limit, @limit
-
- return other
+ # This is the only mutable state:
+ @table = @table.dup
end
-
+
+ # Current table of header key-value pairs.
+ attr :table
+
+ attr :huffman
+ attr :index
+
+ attr :table_size
+
# Finds an entry in current dynamic table by index.
# Note that index is zero-based in this module.
#
# If the index is greater than the last index in the static table,
# an entry in the dynamic table is dereferenced.
@@ -173,11 +163,11 @@
# @return [Array] +[name, value]+ header field that is added to the decoded header list
def decode(command)
emit = nil
case command[:type]
- when :changetablesize
+ when :change_table_size
self.table_size = command[:value]
when :indexed
# Indexed Representation
# An _indexed representation_ entails the following actions:
@@ -187,11 +177,11 @@
idx = command[:name]
k, v = dereference(idx)
emit = [k, v]
- when :incremental, :noindex, :neverindexed
+ when :incremental, :no_index, :never_indexed
# A _literal representation_ that is _not added_ to the dynamic table
# entails the following action:
# o The header field is added to the decoded header list.
# A _literal representation_ that is _added_ to the dynamic table
@@ -217,26 +207,26 @@
end
return emit
end
- # Plan header compression according to +@options [:index]+
+ # Plan header compression according to +@index+
# :never Do not use dynamic table or static table reference at all.
# :static Use static table only.
# :all Use all of them.
#
# @param headers [Array] +[[name, value], ...]+
# @return [Array] array of commands
def encode(headers)
commands = []
- # Literals commands are marked with :noindex when index is not used
- noindex = [:static, :never].include?(@options[:index])
+ # Literals commands are marked with :no_index when index is not used
+ no_index = [:static, :never].include?(@index)
headers.each do |field, value|
command = add_command(field, value)
- command[:type] = :noindex if noindex && command[:type] == :incremental
+ command[:type] = :no_index if no_index && command[:type] == :incremental
commands << command
decode(command)
end
@@ -245,11 +235,11 @@
# Emits command for a header.
# Prefer static table over dynamic table.
# Prefer exact match over name-only match.
#
- # +@options [:index]+ controls whether to use the dynamic table,
+ # +@index+ controls whether to use the dynamic table,
# static table, or both.
# :never Do not use dynamic table or static table reference at all.
# :static Use static table only.
# :all Use all of them.
#
@@ -257,21 +247,21 @@
# @return [Hash] command
def add_command(*header)
exact = nil
name_only = nil
- if [:all, :static].include?(@options[:index])
+ if [:all, :static].include?(@index)
STATIC_TABLE.each_index do |i|
if STATIC_TABLE[i] == header
exact ||= i
break
elsif STATIC_TABLE[i].first == header.first
name_only ||= i
end
end
end
- if [:all].include?(@options[:index]) && !exact
+ if [:all].include?(@index) && !exact
@table.each_index do |i|
if @table[i] == header
exact ||= i + STATIC_TABLE.size
break
elsif @table[i].first == header.first
@@ -289,12 +279,12 @@
end
end
# Alter dynamic table size.
# When the size is reduced, some headers might be evicted.
- def table_size=(size)
- @limit = size
+ def table_size= size
+ @table_size = size
size_check(nil)
end
# Returns current table size in octets
# @return [Integer]
@@ -312,26 +302,26 @@
def add_to_table(command)
return unless size_check(command)
@table.unshift(command)
end
- # To keep the dynamic table size lower than or equal to @limit,
+ # To keep the dynamic table size lower than or equal to @table_size,
# remove one or more entries at the end of the dynamic table.
#
# @param command [Hash]
# @return [Boolean] whether +command+ fits in the dynamic table.
def size_check(command)
cursize = current_table_size
cmdsize = command.nil? ? 0 : command[0].bytesize + command[1].bytesize + 32
- while cursize + cmdsize > @limit
+ while cursize + cmdsize > @table_size
break if @table.empty?
e = @table.pop
cursize -= e[0].bytesize + e[1].bytesize + 32
end
- cmdsize <= @limit
+ cmdsize <= @table_size
end
end
end
end