protocol-hpack 1.4.3 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,9 +6,10 @@
6
6
  # Copyright, 2015, by Tamir Duberstein.
7
7
  # Copyright, 2018-2024, by Samuel Williams.
8
8
  # Copyright, 2022, by Daniel Morrison.
9
+ # Copyright, 2024, by Nathan Froyd.
9
10
 
10
- require_relative 'huffman/machine'
11
- require_relative 'error'
11
+ require_relative "huffman/machine"
12
+ require_relative "error"
12
13
 
13
14
  module Protocol
14
15
  module HPACK
@@ -22,10 +23,10 @@ module Protocol
22
23
  #
23
24
  # @param str [String]
24
25
  # @return [String] binary string
25
- def encode(str)
26
+ def self.encode(str)
26
27
  bitstring = str.each_byte.map {|chr| ENCODE_TABLE[chr]}.join
27
- bitstring << '1' * ((8 - bitstring.size) % 8)
28
- [bitstring].pack('B*')
28
+ bitstring << "1" * ((8 - bitstring.size) % 8)
29
+ [bitstring].pack("B*")
29
30
  end
30
31
 
31
32
  # Decodes provided Huffman coded string.
@@ -33,14 +34,15 @@ module Protocol
33
34
  # @param buf [Buffer]
34
35
  # @return [String] binary string
35
36
  # @raise [CompressionError] when Huffman coded string is malformed
36
- def decode(buffer)
37
+ def self.decode(buffer)
37
38
  emit = String.new.b
38
39
  state = 0 # start state
39
40
 
40
41
  mask = (1 << BITS_AT_ONCE) - 1
41
42
  buffer.each_byte do |c|
42
- (8 / BITS_AT_ONCE - 1).downto(0) do |shift|
43
- branch = (c >> (shift * BITS_AT_ONCE)) & mask
43
+ shift = BITS_AT_ONCE
44
+ while shift >= 0
45
+ branch = (c >> shift) & mask
44
46
 
45
47
  # MACHINE[state] = [final, [transitions]]
46
48
  # [final] unfinished bits so far are prefix of the EOS code.
@@ -49,14 +51,15 @@ module Protocol
49
51
  # [next] next state number.
50
52
  value, state = MACHINE[state][branch]
51
53
 
52
- raise CompressionError, 'Huffman decode error (EOS found)' if value == EOS
54
+ raise CompressionError, "Huffman decode error (EOS found)" if value == EOS
53
55
 
54
56
  emit << value.chr if value
57
+ shift -= BITS_AT_ONCE
55
58
  end
56
59
  end
57
60
  # Check whether partial input is correctly filled
58
61
  unless state <= MAX_FINAL_STATE
59
- raise CompressionError, 'Huffman decode error (EOS invalid)'
62
+ raise CompressionError, "Huffman decode error (EOS invalid)"
60
63
  end
61
64
  emit.force_encoding(Encoding::BINARY)
62
65
  end
@@ -322,7 +325,7 @@ module Protocol
322
325
  [0x3fffffff, 30],
323
326
  ].each(&:freeze).freeze
324
327
 
325
- ENCODE_TABLE = CODES.map {|c, l| [c].pack('N').unpack1('B*')[-l..-1]}.each(&:freeze).freeze
328
+ ENCODE_TABLE = CODES.map {|c, l| [c].pack("N").unpack1("B*")[-l..-1]}.each(&:freeze).freeze
326
329
  end
327
330
  end
328
331
  end
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Protocol
7
7
  module HPACK
8
- VERSION = "1.4.3"
8
+ VERSION = "1.5.1"
9
9
  end
10
10
  end
@@ -5,5 +5,5 @@
5
5
 
6
6
  require_relative "hpack/version"
7
7
 
8
- require_relative 'hpack/compressor'
9
- require_relative 'hpack/decompressor'
8
+ require_relative "hpack/compressor"
9
+ require_relative "hpack/decompressor"
data/license.md CHANGED
@@ -15,6 +15,8 @@ Copyright, 2020, by Olle Jonsson.
15
15
  Copyright, 2020, by Justin Mazzocchi.
16
16
  Copyright, 2022, by Daniel Morrison.
17
17
  Copyright, 2022, by Felix Yan.
18
+ Copyright, 2024, by Maruth Goyal.
19
+ Copyright, 2024, by Nathan Froyd.
18
20
 
19
21
  Permission is hereby granted, free of charge, to any person obtaining a copy
20
22
  of this software and associated documentation files (the "Software"), to deal
data/readme.md CHANGED
@@ -10,6 +10,11 @@ Please see the [project documentation](https://socketry.github.io/protocol-hpack
10
10
 
11
11
  - [Getting Started](https://socketry.github.io/protocol-hpack/guides/getting-started/index) - This guide explains how to use the `protocol-hpack` gem to compress and decompress HTTP/2 headers using HPACK.
12
12
 
13
+ ## See Also
14
+
15
+ - [protocol-http2](https://github.com/socketry/protocol-http2) - Provides an HTTP/2 client and server implementation.
16
+ - [async-http](https://github.com/socketry/async-http) - Provides a complete HTTP client and server implementation on top of Async.
17
+
13
18
  ## Contributing
14
19
 
15
20
  We welcome contributions to this project.
@@ -22,13 +27,8 @@ We welcome contributions to this project.
22
27
 
23
28
  ### Developer Certificate of Origin
24
29
 
25
- This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted.
30
+ In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
26
31
 
27
- ### Contributor Covenant
28
-
29
- This project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.
30
-
31
- ## See Also
32
+ ### Community Guidelines
32
33
 
33
- - [protocol-http2](https://github.com/socketry/protocol-http2) - Provides an HTTP/2 client and server implementation.
34
- - [async-http](https://github.com/socketry/async-http) - Provides a complete HTTP client and server implementation on top of Async.
34
+ This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-hpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  - Ilya Grigorik
9
9
  - Tamir Duberstein
10
+ - Nathan Froyd
10
11
  - Kaoru Maeda
11
12
  - Tiago Cardoso
12
13
  - Byron Formwalt
@@ -18,6 +19,7 @@ authors:
18
19
  - Justin Mazzocchi
19
20
  - Kenichi Nakamura
20
21
  - Kien Nguyen Trung
22
+ - Maruth Goyal
21
23
  - Olle Jonsson
22
24
  autorequire:
23
25
  bindir: bin
@@ -51,7 +53,7 @@ cert_chain:
51
53
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
52
54
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
53
55
  -----END CERTIFICATE-----
54
- date: 2024-03-12 00:00:00.000000000 Z
56
+ date: 2024-09-13 00:00:00.000000000 Z
55
57
  dependencies: []
56
58
  description:
57
59
  email:
@@ -65,17 +67,17 @@ files:
65
67
  - lib/protocol/hpack/decompressor.rb
66
68
  - lib/protocol/hpack/error.rb
67
69
  - lib/protocol/hpack/huffman.rb
70
+ - lib/protocol/hpack/huffman/generator.rb
68
71
  - lib/protocol/hpack/huffman/machine.rb
69
72
  - lib/protocol/hpack/version.rb
70
73
  - license.md
71
74
  - readme.md
72
- - tasks/huffman.rake
73
- - tasks/huffman.rb
74
75
  homepage: https://github.com/socketry/http-hpack
75
76
  licenses:
76
77
  - MIT
77
78
  metadata:
78
79
  documentation_uri: https://socketry.github.io/protocol-hpack/
80
+ source_code_uri: https://github.com/socketry/http-hpack.git
79
81
  post_install_message:
80
82
  rdoc_options: []
81
83
  require_paths:
@@ -84,14 +86,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
86
  requirements:
85
87
  - - ">="
86
88
  - !ruby/object:Gem::Version
87
- version: '3.0'
89
+ version: '3.1'
88
90
  required_rubygems_version: !ruby/object:Gem::Requirement
89
91
  requirements:
90
92
  - - ">="
91
93
  - !ruby/object:Gem::Version
92
94
  version: '0'
93
95
  requirements: []
94
- rubygems_version: 3.5.3
96
+ rubygems_version: 3.5.11
95
97
  signing_key:
96
98
  specification_version: 4
97
99
  summary: A compresssor and decompressor for HTTP/2's HPACK format.
metadata.gz.sig CHANGED
Binary file
data/tasks/huffman.rake DELETED
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- namespace :huffman do
4
- desc 'Generate the huffman state table'
5
- task :generate_table do
6
- require_relative 'huffman'
7
-
8
- Huffman::Node.generate_state_table
9
- end
10
- end
data/tasks/huffman.rb DELETED
@@ -1,173 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2014, by Kaoru Maeda.
5
- # Copyright, 2015, by Tamir Duberstein.
6
- # Copyright, 2015, by Ilya Grigorik.
7
- # Copyright, 2016, by George Ulmer.
8
- # Copyright, 2018-2024, by Samuel Williams.
9
-
10
- require_relative '../lib/http/hpack/huffman'
11
-
12
- require 'set'
13
-
14
- module Huffman
15
- BITS_AT_ONCE = HTTP::HPACK::Huffman::BITS_AT_ONCE
16
- EOS = 256
17
-
18
- class Node
19
- attr_accessor :next, :emit, :final, :depth
20
- attr_accessor :transitions
21
- attr_accessor :id
22
- @@id = 0 # rubocop:disable Style/ClassVars
23
- def initialize(depth)
24
- @next = [nil, nil]
25
- @id = @@id
26
- @@id += 1 # rubocop:disable Style/ClassVars
27
- @final = false
28
- @depth = depth
29
- end
30
-
31
- def add(code, len, chr)
32
- self.final = true if chr == EOS && @depth <= 7
33
- if len.zero?
34
- @emit = chr
35
- else
36
- bit = (code & (1 << (len - 1))).zero? ? 0 : 1
37
- node = @next[bit] ||= Node.new(@depth + 1)
38
- node.add(code, len - 1, chr)
39
- end
40
- end
41
-
42
- class Transition
43
- attr_accessor :emit, :node
44
- def initialize(emit, node)
45
- @emit = emit
46
- @node = node
47
- end
48
- end
49
-
50
- def self.generate_tree
51
- @root = new(0)
52
- HTTP::HPACK::Huffman::CODES.each_with_index do |c, chr|
53
- code, len = c
54
- @root.add(code, len, chr)
55
- end
56
- puts "#{@@id} nodes"
57
- @root
58
- end
59
-
60
- def self.generate_machine
61
- generate_tree
62
- togo = Set[@root]
63
- @states = Set[@root]
64
-
65
- until togo.empty?
66
- node = togo.first
67
- togo.delete(node)
68
-
69
- next if node.transitions
70
- node.transitions = Array[1 << BITS_AT_ONCE]
71
-
72
- (1 << BITS_AT_ONCE).times do |input|
73
- n = node
74
- emit = ''
75
- (BITS_AT_ONCE - 1).downto(0) do |i|
76
- bit = (input & (1 << i)).zero? ? 0 : 1
77
- n = n.next[bit]
78
- next unless n.emit
79
- if n.emit == EOS
80
- emit = EOS # cause error on decoding
81
- else
82
- emit << n.emit.chr(Encoding::BINARY) unless emit == EOS
83
- end
84
- n = @root
85
- end
86
- node.transitions[input] = Transition.new(emit, n)
87
- togo << n
88
- @states << n
89
- end
90
- end
91
- puts "#{@states.size} states"
92
- @root
93
- end
94
-
95
- def self.generate_state_table
96
- generate_machine
97
- state_id = {}
98
- id_state = {}
99
- state_id[@root] = 0
100
- id_state[0] = @root
101
- max_final = 0
102
- id = 1
103
- (@states - [@root]).sort_by {|s| s.final ? 0 : 1}.each do |s|
104
- state_id[s] = id
105
- id_state[id] = s
106
- max_final = id if s.final
107
- id += 1
108
- end
109
-
110
- File.open(File.expand_path('../lib/http/hpack/huffman/machine.rb', File.dirname(__FILE__)), 'w') do |f|
111
- f.print <<HEADER
112
- # frozen_string_literal: true
113
-
114
- # Released under the MIT License.
115
- # Copyright, 2018-2024, by Samuel Williams.
116
-
117
- # Machine generated Huffman decoder state machine.
118
- # DO NOT EDIT THIS FILE.
119
-
120
- module Protocol
121
- module HPACK
122
- class Huffman
123
- # :nodoc:
124
- MAX_FINAL_STATE = #{max_final}
125
- MACHINE = [
126
- HEADER
127
- id.times do |i|
128
- n = id_state[i]
129
- f.print "\t\t\t\t["
130
- string = (1 << BITS_AT_ONCE).times.map do |t|
131
- transition = n.transitions.fetch(t)
132
- emit = transition.emit
133
- unless emit == EOS
134
- bytes = emit.bytes
135
- fail ArgumentError if bytes.size > 1
136
- emit = bytes.first
137
- end
138
- "[#{emit.inspect}, #{state_id.fetch(transition.node)}]"
139
- end.join(', ')
140
- f.print(string)
141
- f.print "],\n"
142
- end
143
- f.print <<TAILER
144
- ].each {|arr| arr.each {|subarr| subarr.each(&:freeze)}.freeze}.freeze
145
- end
146
- end
147
- end
148
- TAILER
149
- end
150
- end
151
-
152
- class << self
153
- attr_reader :root
154
- end
155
-
156
- # Test decoder
157
- def self.decode(input)
158
- emit = ''
159
- n = root
160
- nibbles = input.unpack('C*').flat_map {|b| [((b & 0xf0) >> 4), b & 0xf]}
161
- until nibbles.empty?
162
- nb = nibbles.shift
163
- t = n.transitions[nb]
164
- emit << t.emit
165
- n = t.node
166
- end
167
- unless n.final && nibbles.all? {|x| x == 0xf}
168
- puts "len = #{emit.size} n.final = #{n.final} nibbles = #{nibbles}"
169
- end
170
- emit
171
- end
172
- end
173
- end