protocol-hpack 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/protocol/hpack/compressor.rb +7 -10
- data/lib/protocol/hpack/context.rb +1 -1
- data/lib/protocol/hpack/decompressor.rb +2 -2
- data/lib/protocol/hpack/huffman/generator.rb +186 -0
- data/lib/protocol/hpack/huffman/machine.rb +254 -254
- data/lib/protocol/hpack/huffman.rb +7 -7
- data/lib/protocol/hpack/version.rb +1 -1
- data/lib/protocol/hpack.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +3 -4
- metadata.gz.sig +0 -0
- data/tasks/huffman.rake +0 -10
- data/tasks/huffman.rb +0 -174
@@ -8,8 +8,8 @@
|
|
8
8
|
# Copyright, 2022, by Daniel Morrison.
|
9
9
|
# Copyright, 2024, by Nathan Froyd.
|
10
10
|
|
11
|
-
require_relative
|
12
|
-
require_relative
|
11
|
+
require_relative "huffman/machine"
|
12
|
+
require_relative "error"
|
13
13
|
|
14
14
|
module Protocol
|
15
15
|
module HPACK
|
@@ -25,8 +25,8 @@ module Protocol
|
|
25
25
|
# @return [String] binary string
|
26
26
|
def self.encode(str)
|
27
27
|
bitstring = str.each_byte.map {|chr| ENCODE_TABLE[chr]}.join
|
28
|
-
bitstring <<
|
29
|
-
[bitstring].pack(
|
28
|
+
bitstring << "1" * ((8 - bitstring.size) % 8)
|
29
|
+
[bitstring].pack("B*")
|
30
30
|
end
|
31
31
|
|
32
32
|
# Decodes provided Huffman coded string.
|
@@ -51,7 +51,7 @@ module Protocol
|
|
51
51
|
# [next] next state number.
|
52
52
|
value, state = MACHINE[state][branch]
|
53
53
|
|
54
|
-
raise CompressionError,
|
54
|
+
raise CompressionError, "Huffman decode error (EOS found)" if value == EOS
|
55
55
|
|
56
56
|
emit << value.chr if value
|
57
57
|
shift -= BITS_AT_ONCE
|
@@ -59,7 +59,7 @@ module Protocol
|
|
59
59
|
end
|
60
60
|
# Check whether partial input is correctly filled
|
61
61
|
unless state <= MAX_FINAL_STATE
|
62
|
-
raise CompressionError,
|
62
|
+
raise CompressionError, "Huffman decode error (EOS invalid)"
|
63
63
|
end
|
64
64
|
emit.force_encoding(Encoding::BINARY)
|
65
65
|
end
|
@@ -325,7 +325,7 @@ module Protocol
|
|
325
325
|
[0x3fffffff, 30],
|
326
326
|
].each(&:freeze).freeze
|
327
327
|
|
328
|
-
ENCODE_TABLE = CODES.map {|c, l| [c].pack(
|
328
|
+
ENCODE_TABLE = CODES.map {|c, l| [c].pack("N").unpack1("B*")[-l..-1]}.each(&:freeze).freeze
|
329
329
|
end
|
330
330
|
end
|
331
331
|
end
|
data/lib/protocol/hpack.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol-hpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -53,7 +53,7 @@ cert_chain:
|
|
53
53
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
54
54
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
55
55
|
-----END CERTIFICATE-----
|
56
|
-
date: 2024-
|
56
|
+
date: 2024-09-13 00:00:00.000000000 Z
|
57
57
|
dependencies: []
|
58
58
|
description:
|
59
59
|
email:
|
@@ -67,12 +67,11 @@ files:
|
|
67
67
|
- lib/protocol/hpack/decompressor.rb
|
68
68
|
- lib/protocol/hpack/error.rb
|
69
69
|
- lib/protocol/hpack/huffman.rb
|
70
|
+
- lib/protocol/hpack/huffman/generator.rb
|
70
71
|
- lib/protocol/hpack/huffman/machine.rb
|
71
72
|
- lib/protocol/hpack/version.rb
|
72
73
|
- license.md
|
73
74
|
- readme.md
|
74
|
-
- tasks/huffman.rake
|
75
|
-
- tasks/huffman.rb
|
76
75
|
homepage: https://github.com/socketry/http-hpack
|
77
76
|
licenses:
|
78
77
|
- MIT
|
metadata.gz.sig
CHANGED
Binary file
|
data/tasks/huffman.rake
DELETED
data/tasks/huffman.rb
DELETED
@@ -1,174 +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
|
-
# Copyright, 2024, by Nathan Froyd.
|
10
|
-
|
11
|
-
require_relative '../lib/protocol/hpack/huffman'
|
12
|
-
|
13
|
-
require 'set'
|
14
|
-
|
15
|
-
module Huffman
|
16
|
-
BITS_AT_ONCE = Protocol::HPACK::Huffman::BITS_AT_ONCE
|
17
|
-
EOS = 256
|
18
|
-
|
19
|
-
class Node
|
20
|
-
attr_accessor :next, :emit, :final, :depth
|
21
|
-
attr_accessor :transitions
|
22
|
-
attr_accessor :id
|
23
|
-
@@id = 0 # rubocop:disable Style/ClassVars
|
24
|
-
def initialize(depth)
|
25
|
-
@next = [nil, nil]
|
26
|
-
@id = @@id
|
27
|
-
@@id += 1 # rubocop:disable Style/ClassVars
|
28
|
-
@final = false
|
29
|
-
@depth = depth
|
30
|
-
end
|
31
|
-
|
32
|
-
def add(code, len, chr)
|
33
|
-
self.final = true if chr == EOS && @depth <= 7
|
34
|
-
if len.zero?
|
35
|
-
@emit = chr
|
36
|
-
else
|
37
|
-
bit = (code & (1 << (len - 1))).zero? ? 0 : 1
|
38
|
-
node = @next[bit] ||= Node.new(@depth + 1)
|
39
|
-
node.add(code, len - 1, chr)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class Transition
|
44
|
-
attr_accessor :emit, :node
|
45
|
-
def initialize(emit, node)
|
46
|
-
@emit = emit
|
47
|
-
@node = node
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.generate_tree
|
52
|
-
@root = new(0)
|
53
|
-
Protocol::HPACK::Huffman::CODES.each_with_index do |c, chr|
|
54
|
-
code, len = c
|
55
|
-
@root.add(code, len, chr)
|
56
|
-
end
|
57
|
-
puts "#{@@id} nodes"
|
58
|
-
@root
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.generate_machine
|
62
|
-
generate_tree
|
63
|
-
togo = Set[@root]
|
64
|
-
@states = Set[@root]
|
65
|
-
|
66
|
-
until togo.empty?
|
67
|
-
node = togo.first
|
68
|
-
togo.delete(node)
|
69
|
-
|
70
|
-
next if node.transitions
|
71
|
-
node.transitions = Array[1 << BITS_AT_ONCE]
|
72
|
-
|
73
|
-
(1 << BITS_AT_ONCE).times do |input|
|
74
|
-
n = node
|
75
|
-
emit = +''
|
76
|
-
(BITS_AT_ONCE - 1).downto(0) do |i|
|
77
|
-
bit = (input & (1 << i)).zero? ? 0 : 1
|
78
|
-
n = n.next[bit]
|
79
|
-
next unless n.emit
|
80
|
-
if n.emit == EOS
|
81
|
-
emit = EOS # cause error on decoding
|
82
|
-
else
|
83
|
-
emit << n.emit.chr(Encoding::BINARY) unless emit == EOS
|
84
|
-
end
|
85
|
-
n = @root
|
86
|
-
end
|
87
|
-
node.transitions[input] = Transition.new(emit, n)
|
88
|
-
togo << n
|
89
|
-
@states << n
|
90
|
-
end
|
91
|
-
end
|
92
|
-
puts "#{@states.size} states"
|
93
|
-
@root
|
94
|
-
end
|
95
|
-
|
96
|
-
def self.generate_state_table
|
97
|
-
generate_machine
|
98
|
-
state_id = {}
|
99
|
-
id_state = {}
|
100
|
-
state_id[@root] = 0
|
101
|
-
id_state[0] = @root
|
102
|
-
max_final = 0
|
103
|
-
id = 1
|
104
|
-
(@states - [@root]).sort_by {|s| s.final ? 0 : 1}.each do |s|
|
105
|
-
state_id[s] = id
|
106
|
-
id_state[id] = s
|
107
|
-
max_final = id if s.final
|
108
|
-
id += 1
|
109
|
-
end
|
110
|
-
|
111
|
-
File.open(File.expand_path('../lib/protocol/hpack/huffman/machine.rb', File.dirname(__FILE__)), 'w') do |f|
|
112
|
-
f.print <<HEADER
|
113
|
-
# frozen_string_literal: true
|
114
|
-
|
115
|
-
# Released under the MIT License.
|
116
|
-
# Copyright, 2018-2024, by Samuel Williams.
|
117
|
-
|
118
|
-
# Machine generated Huffman decoder state machine.
|
119
|
-
# DO NOT EDIT THIS FILE.
|
120
|
-
|
121
|
-
module Protocol
|
122
|
-
module HPACK
|
123
|
-
class Huffman
|
124
|
-
# :nodoc:
|
125
|
-
MAX_FINAL_STATE = #{max_final}
|
126
|
-
MACHINE = [
|
127
|
-
HEADER
|
128
|
-
id.times do |i|
|
129
|
-
n = id_state[i]
|
130
|
-
f.print "\t\t\t\t["
|
131
|
-
string = (1 << BITS_AT_ONCE).times.map do |t|
|
132
|
-
transition = n.transitions.fetch(t)
|
133
|
-
emit = transition.emit
|
134
|
-
unless emit == EOS
|
135
|
-
bytes = emit.bytes
|
136
|
-
fail ArgumentError if bytes.size > 1
|
137
|
-
emit = bytes.first
|
138
|
-
end
|
139
|
-
"[#{emit.inspect}, #{state_id.fetch(transition.node)}]"
|
140
|
-
end.join(', ')
|
141
|
-
f.print(string)
|
142
|
-
f.print "],\n"
|
143
|
-
end
|
144
|
-
f.print <<TAILER
|
145
|
-
].each {|arr| arr.each {|subarr| subarr.each(&:freeze)}.freeze}.freeze
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
TAILER
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
class << self
|
154
|
-
attr_reader :root
|
155
|
-
end
|
156
|
-
|
157
|
-
# Test decoder
|
158
|
-
def self.decode(input)
|
159
|
-
emit = ''
|
160
|
-
n = root
|
161
|
-
nibbles = input.unpack('C*').flat_map {|b| [((b & 0xf0) >> 4), b & 0xf]}
|
162
|
-
until nibbles.empty?
|
163
|
-
nb = nibbles.shift
|
164
|
-
t = n.transitions[nb]
|
165
|
-
emit << t.emit
|
166
|
-
n = t.node
|
167
|
-
end
|
168
|
-
unless n.final && nibbles.all? {|x| x == 0xf}
|
169
|
-
puts "len = #{emit.size} n.final = #{n.final} nibbles = #{nibbles}"
|
170
|
-
end
|
171
|
-
emit
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|