Module: Biryani::HPACK::Field

Defined in:
lib/biryani/hpack/field.rb

Overview

rubocop: disable Metrics/ModuleLength

Class Method Summary collapse

Class Method Details

.decode(io, cursor, dynamic_table) ⇒ Array, Integer

rubocop: disable Metrics/CyclomaticComplexity rubocop: disable Metrics/PerceivedComplexity

Parameters:

Returns:



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/biryani/hpack/field.rb', line 109

def self.decode(io, cursor, dynamic_table)
  byte = io.get_value(:U8, cursor)
  if (byte & 0b10000000).positive?
    decode_indexed(io, cursor, dynamic_table)
  elsif byte == 0b01000000
    decode_literal_field_incremental_indexing(io, cursor, dynamic_table)
  elsif (byte & 0b01000000).positive?
    decode_literal_value_incremental_indexing(io, cursor, dynamic_table)
  elsif (byte & 0b00100000).positive?
    decode_dynamic_table_size_update(io, cursor, dynamic_table)
  elsif byte == 0b00010000
    decode_literal_field_never_indexed(io, cursor)
  elsif (byte & 0b00010000).positive?
    decode_literal_value_never_indexed(io, cursor, dynamic_table)
  elsif byte.zero?
    decode_literal_field_without_indexing(io, cursor)
  elsif (byte & 0b11110000).zero?
    decode_literal_value_without_indexing(io, cursor, dynamic_table)
  else
    raise 'unreachable'
  end
end

.decode_dynamic_table_size_update(io, cursor, dynamic_table) ⇒ nil, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 1 | Max size (5+) | +---+---------------------------+ https://datatracker.ietf.org/doc/html/rfc7541#section-6.3

Parameters:

Returns:

Raises:



217
218
219
220
221
222
223
224
225
# File 'lib/biryani/hpack/field.rb', line 217

def self.decode_dynamic_table_size_update(io, cursor, dynamic_table)
  raise Error::HPACKDecodeError unless cursor.zero? || (io.get_value(:U8, 0) & 0b00100000).positive? && Integer.decode(io, 5, 0)[1] == cursor

  max_size, c = Integer.decode(io, 5, cursor)
  raise Error::HPACKDecodeError if max_size > dynamic_table.limit

  dynamic_table.chomp!(max_size)
  [nil, c]
end

.decode_indexed(io, cursor, dynamic_table) ⇒ Array, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 1 | Index (7+) | +---+---------------------------+ https://datatracker.ietf.org/doc/html/rfc7541#section-6.1

Parameters:

Returns:



146
147
148
149
150
# File 'lib/biryani/hpack/field.rb', line 146

def self.decode_indexed(io, cursor, dynamic_table)
  index, c = Integer.decode(io, 7, cursor)

  [dynamic_table.entry_at(index), c]
end

.decode_literal_field_incremental_indexing(io, cursor, dynamic_table) ⇒ Array, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 1 | 0 | +---+---+-----------------------+ | H | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | ------------------------------- https://datatracker.ietf.org/doc/html/rfc7541#section-6.2.1

Parameters:

Returns:



172
173
174
175
176
177
178
# File 'lib/biryani/hpack/field.rb', line 172

def self.decode_literal_field_incremental_indexing(io, cursor, dynamic_table)
  name, c = String.decode(io, cursor + 1)
  value, c = String.decode(io, c)
  dynamic_table.store(name, value)

  [[name, value], c]
end

.decode_literal_field_never_indexed(io, cursor) ⇒ Array, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 1 | 0 | +---+---+-----------------------+ | H | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | ------------------------------- https://datatracker.ietf.org/doc/html/rfc7541#section-6.2.3

Parameters:

Returns:



246
247
248
249
250
251
# File 'lib/biryani/hpack/field.rb', line 246

def self.decode_literal_field_never_indexed(io, cursor)
  name, c = String.decode(io, cursor + 1)
  value, c = String.decode(io, c)

  [[name, value], c]
end

.decode_literal_field_without_indexing(io, cursor) ⇒ Array, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 1 | 0 | +---+---+-----------------------+ | H | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | ------------------------------- https://datatracker.ietf.org/doc/html/rfc7541#section-6.2.2

Parameters:

Returns:



296
297
298
299
300
301
# File 'lib/biryani/hpack/field.rb', line 296

def self.decode_literal_field_without_indexing(io, cursor)
  name, c = String.decode(io, cursor + 1)
  value, c = String.decode(io, c)

  [[name, value], c]
end

.decode_literal_value_incremental_indexing(io, cursor, dynamic_table) ⇒ Array, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 1 | Index (6+) | +---+---+-----------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | ------------------------------- https://datatracker.ietf.org/doc/html/rfc7541#section-6.2.1

Parameters:

Returns:



196
197
198
199
200
201
202
203
# File 'lib/biryani/hpack/field.rb', line 196

def self.decode_literal_value_incremental_indexing(io, cursor, dynamic_table)
  index, c = Integer.decode(io, 6, cursor)
  name = dynamic_table.name_at(index)
  value, c = String.decode(io, c)
  dynamic_table.store(name, value)

  [[name, value], c]
end

.decode_literal_value_never_indexed(io, cursor, dynamic_table) ⇒ Array, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 1 | Index (4+) | +---+---+-----------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | ------------------------------- https://datatracker.ietf.org/doc/html/rfc7541#section-6.2.3

Parameters:

Returns:



269
270
271
272
273
274
275
# File 'lib/biryani/hpack/field.rb', line 269

def self.decode_literal_value_never_indexed(io, cursor, dynamic_table)
  index, c = Integer.decode(io, 4, cursor)
  name = dynamic_table.name_at(index)
  value, c = String.decode(io, c)

  [[name, value], c]
end

.decode_literal_value_without_indexing(io, cursor, dynamic_table) ⇒ Array, Integer

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 0 | Index (4+) | +---+---+-----------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | -------------------------------

Parameters:

Returns:



318
319
320
321
322
323
324
# File 'lib/biryani/hpack/field.rb', line 318

def self.decode_literal_value_without_indexing(io, cursor, dynamic_table)
  index, c = Integer.decode(io, 4, cursor)
  name = dynamic_table.name_at(index)
  value, c = String.decode(io, c)

  [[name, value], c]
end

.encode(name, value, dynamic_table) ⇒ String

Parameters:

Returns:



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/biryani/hpack/field.rb', line 10

def self.encode(name, value, dynamic_table)
  case find(name, value, dynamic_table)
  in Some(index, nil)
    res = encode_indexed(index)
  in Some(index, v)
    res = encode_literal_value(index, v)
    dynamic_table.store(name, v)
  in None
    res = encode_literal_field(name, value)
    dynamic_table.store(name, value)
  end

  res
end

.encode_indexed(index) ⇒ String

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 1 | Index (7+) | +---+---------------------------+ https://datatracker.ietf.org/doc/html/rfc7541#section-6.1

Parameters:

Returns:



57
58
59
# File 'lib/biryani/hpack/field.rb', line 57

def self.encode_indexed(index)
  Integer.encode(index, 7, 0b10000000)
end

.encode_literal_field(name, value) ⇒ String

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 1 | 0 | +---+---+-----------------------+ | H | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | ------------------------------- https://datatracker.ietf.org/doc/html/rfc7541#section-6.2.1

Parameters:

Returns:



97
98
99
# File 'lib/biryani/hpack/field.rb', line 97

def self.encode_literal_field(name, value)
  "\x40#{String.encode(name)}#{String.encode(value)}"
end

.encode_literal_value(index, value) ⇒ String

0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 1 | Index (6+) | +---+---+-----------------------+ | H | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | ------------------------------- https://datatracker.ietf.org/doc/html/rfc7541#section-6.2.1

Parameters:

Returns:



75
76
77
# File 'lib/biryani/hpack/field.rb', line 75

def self.encode_literal_value(index, value)
  Integer.encode(index, 6, 0b01000000) + String.encode(value)
end

.find(name, value, dynamic_table) ⇒ Some, None

rubocop: disable Metrics/CyclomaticComplexity

Parameters:

Returns:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/biryani/hpack/field.rb', line 31

def self.find(name, value, dynamic_table)
  found, i = STATIC_TABLE.each_with_index.find { |nv, _| nv[0] == name && nv[1] == value }
  return Some.new(i + 1, nil) unless found.nil?

  found, i = dynamic_table.find_field(name, value)
  return Some.new(i + 1 + STATIC_TABLE_SIZE, nil) unless found.nil?

  found, i = STATIC_TABLE.each_with_index.find { |nv, _| nv[0] == name }
  return Some.new(i + 1, value) unless found.nil?

  found, i = dynamic_table.find_name(name)
  return Some.new(i + 1 + STATIC_TABLE_SIZE, value) unless found.nil?

  None.new
end