omnizip 0.3.13 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/omnizip/algorithm.rb +36 -1
- data/lib/omnizip/algorithms/bzip2.rb +1 -3
- data/lib/omnizip/algorithms/deflate.rb +1 -3
- data/lib/omnizip/algorithms/deflate64.rb +2 -2
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +7 -8
- data/lib/omnizip/algorithms/lzma.rb +1 -1
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +5 -1
- data/lib/omnizip/algorithms/lzma2.rb +4 -12
- data/lib/omnizip/algorithms/zstandard/constants.rb +38 -25
- data/lib/omnizip/algorithms/zstandard/decoder.rb +101 -136
- data/lib/omnizip/algorithms/zstandard/encoder.rb +81 -138
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +17 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +42 -29
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +114 -117
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +434 -222
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +98 -176
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +21 -2
- data/lib/omnizip/algorithms/zstandard/huffman.rb +195 -188
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +232 -255
- data/lib/omnizip/algorithms/zstandard/literals.rb +170 -103
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +47 -199
- data/lib/omnizip/algorithms/zstandard/sequences.rb +260 -252
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +20 -24
- data/lib/omnizip/algorithms.rb +14 -1
- data/lib/omnizip/buffer.rb +1 -2
- data/lib/omnizip/commands/archive_list_command.rb +9 -7
- data/lib/omnizip/convenience.rb +1 -2
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/extraction/selective_extractor.rb +2 -10
- data/lib/omnizip/filter_pipeline.rb +1 -1
- data/lib/omnizip/filter_registry.rb +18 -16
- data/lib/omnizip/filters/bcj2.rb +1 -1
- data/lib/omnizip/filters/bcj_arm.rb +1 -1
- data/lib/omnizip/filters/bcj_arm64.rb +1 -1
- data/lib/omnizip/filters/bcj_ia64.rb +1 -1
- data/lib/omnizip/filters/bcj_ppc.rb +1 -1
- data/lib/omnizip/filters/bcj_sparc.rb +1 -1
- data/lib/omnizip/filters/bcj_x86.rb +1 -1
- data/lib/omnizip/filters.rb +0 -2
- data/lib/omnizip/formats/bzip2_file.rb +0 -7
- data/lib/omnizip/formats/cpio/entry.rb +6 -0
- data/lib/omnizip/formats/cpio.rb +0 -6
- data/lib/omnizip/formats/gzip.rb +0 -7
- data/lib/omnizip/formats/iso/directory_record.rb +7 -0
- data/lib/omnizip/formats/iso.rb +0 -5
- data/lib/omnizip/formats/lzip.rb +0 -7
- data/lib/omnizip/formats/lzma_alone.rb +0 -6
- data/lib/omnizip/formats/msi/entry.rb +6 -0
- data/lib/omnizip/formats/msi.rb +0 -9
- data/lib/omnizip/formats/ole/dirent.rb +6 -0
- data/lib/omnizip/formats/ole.rb +0 -9
- data/lib/omnizip/formats/rar.rb +0 -6
- data/lib/omnizip/formats/rar3/reader.rb +7 -0
- data/lib/omnizip/formats/rar5/reader.rb +7 -0
- data/lib/omnizip/formats/rpm/entry.rb +6 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +7 -0
- data/lib/omnizip/formats/seven_zip.rb +0 -6
- data/lib/omnizip/formats/tar/entry.rb +6 -0
- data/lib/omnizip/formats/tar.rb +2 -10
- data/lib/omnizip/formats/xar/entry.rb +6 -0
- data/lib/omnizip/formats/xar.rb +0 -6
- data/lib/omnizip/formats/zip.rb +0 -6
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +33 -31
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +177 -163
- data/lib/omnizip/implementations.rb +18 -4
- data/lib/omnizip/io/source.rb +3 -0
- data/lib/omnizip/metadata/entry_metadata.rb +7 -0
- data/lib/omnizip/parallel/engine.rb +48 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +5 -16
- data/lib/omnizip/parallel/parallel_extractor.rb +5 -16
- data/lib/omnizip/parallel.rb +1 -0
- data/lib/omnizip/profile/profile_registry.rb +1 -2
- data/lib/omnizip/registry.rb +0 -1
- data/lib/omnizip/rubyzip_compat.rb +0 -1
- data/lib/omnizip/temp/temp_file.rb +1 -2
- data/lib/omnizip/version.rb +1 -1
- data/lib/omnizip/zip/entry.rb +7 -0
- data/lib/omnizip/zip/file.rb +4 -8
- data/lib/omnizip.rb +1 -1
- metadata +7 -6
- data/lib/omnizip/filters/filter_base.rb +0 -6
- data/lib/omnizip/filters/registration.rb +0 -22
- data/lib/omnizip/filters/registry.rb +0 -111
- data/lib/omnizip/format_registry.rb +0 -100
|
@@ -23,10 +23,12 @@
|
|
|
23
23
|
module Omnizip
|
|
24
24
|
module Algorithms
|
|
25
25
|
class Zstandard
|
|
26
|
-
# Pure Ruby Zstandard encoder (RFC 8878)
|
|
26
|
+
# Pure Ruby Zstandard encoder (RFC 8878).
|
|
27
27
|
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
28
|
+
# Emits a single-segment frame. Each 128 KiB chunk of input
|
|
29
|
+
# becomes one block, choosing whichever is smallest: RLE, a
|
|
30
|
+
# Compressed_Block (Huffman-coded literals + an empty sequences
|
|
31
|
+
# section), or a Raw_Block fallback for incompressible data.
|
|
30
32
|
class Encoder
|
|
31
33
|
include Constants
|
|
32
34
|
|
|
@@ -34,177 +36,125 @@ module Omnizip
|
|
|
34
36
|
|
|
35
37
|
# Initialize encoder
|
|
36
38
|
#
|
|
37
|
-
# @param output_stream [IO]
|
|
38
|
-
# @param options [Hash]
|
|
39
|
-
# @option options [Integer] :level
|
|
40
|
-
# @option options [Boolean] :
|
|
39
|
+
# @param output_stream [IO] output for compressed data
|
|
40
|
+
# @param options [Hash]
|
|
41
|
+
# @option options [Integer] :level compression level (1-22)
|
|
42
|
+
# @option options [Boolean] :checksum write the frame checksum
|
|
41
43
|
def initialize(output_stream, options = {})
|
|
42
44
|
@output_stream = output_stream
|
|
43
45
|
@options = options
|
|
44
46
|
@level = options[:level] || DEFAULT_LEVEL
|
|
45
|
-
@
|
|
47
|
+
@checksum = options.fetch(:checksum, false)
|
|
46
48
|
end
|
|
47
49
|
|
|
48
|
-
# Encode data stream
|
|
50
|
+
# Encode a data stream
|
|
49
51
|
#
|
|
50
|
-
# @param data [String]
|
|
51
|
-
# @return [void]
|
|
52
|
+
# @param data [String]
|
|
52
53
|
def encode_stream(data)
|
|
53
|
-
|
|
54
|
+
data = data.dup.force_encoding(Encoding::BINARY)
|
|
54
55
|
write_frame(data)
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
private
|
|
58
59
|
|
|
59
|
-
# Write a complete Zstandard frame
|
|
60
60
|
def write_frame(data)
|
|
61
|
-
# Write magic number
|
|
62
61
|
write_u32le(MAGIC_NUMBER)
|
|
62
|
+
write_frame_header(data)
|
|
63
|
+
write_blocks(data)
|
|
64
|
+
write_u32le(XXHash64.frame_checksum(data)) if @checksum
|
|
65
|
+
end
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
@output_stream.putc(
|
|
70
|
-
@output_stream.putc(
|
|
67
|
+
# Single-segment frame header: no window descriptor, no
|
|
68
|
+
# dictionary; Frame_Content_Size in 1, 2, 4 or 8 bytes.
|
|
69
|
+
def write_frame_header(data)
|
|
70
|
+
size = data.bytesize
|
|
71
|
+
if size < 256
|
|
72
|
+
@output_stream.putc(0x20) # single segment, FCS 1 byte
|
|
73
|
+
@output_stream.putc(size)
|
|
74
|
+
elsif size <= 65_791
|
|
75
|
+
@output_stream.putc(0x60) # single segment, FCS 2 bytes (+256)
|
|
76
|
+
write_u16le(size - 256)
|
|
77
|
+
elsif size <= 0xFFFFFFFF
|
|
78
|
+
@output_stream.putc(0xA0) # single segment, FCS 4 bytes
|
|
79
|
+
write_u32le(size)
|
|
71
80
|
else
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
# Bit 5 = 1 (single segment) = 0x20
|
|
75
|
-
descriptor = 0x80 | 0x20 # 0xA0
|
|
76
|
-
@output_stream.putc(descriptor)
|
|
77
|
-
write_u32le(data.bytesize)
|
|
81
|
+
@output_stream.putc(0xE0) # single segment, FCS 8 bytes
|
|
82
|
+
write_u64le(size)
|
|
78
83
|
end
|
|
79
|
-
|
|
80
|
-
# Write blocks
|
|
81
|
-
write_blocks(data)
|
|
82
|
-
|
|
83
|
-
# Write content checksum (optional, disabled for now)
|
|
84
|
-
# write_u32le(xxhash32(data))
|
|
85
84
|
end
|
|
86
85
|
|
|
87
|
-
# Write blocks containing the data
|
|
88
86
|
def write_blocks(data)
|
|
89
|
-
return if data.empty?
|
|
87
|
+
return write_empty_last_block if data.empty?
|
|
90
88
|
|
|
91
89
|
offset = 0
|
|
92
|
-
max_block_size = BLOCK_MAX_SIZE
|
|
93
|
-
|
|
94
90
|
while offset < data.bytesize
|
|
95
|
-
chunk = data.byteslice(offset,
|
|
91
|
+
chunk = data.byteslice(offset, BLOCK_MAX_SIZE)
|
|
96
92
|
offset += chunk.bytesize
|
|
97
|
-
|
|
98
93
|
is_last = offset >= data.bytesize
|
|
99
|
-
|
|
100
|
-
# Use RLE for repetitive data, otherwise raw blocks
|
|
101
|
-
# Compressed blocks are deferred until decoder fully supports them
|
|
102
|
-
if rle_efficient?(chunk)
|
|
103
|
-
write_rle_block(chunk, is_last)
|
|
104
|
-
else
|
|
105
|
-
write_raw_block(chunk, is_last)
|
|
106
|
-
end
|
|
94
|
+
write_chunk(chunk, is_last)
|
|
107
95
|
end
|
|
108
96
|
end
|
|
109
97
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return false if chunk.bytesize < 3
|
|
113
|
-
|
|
114
|
-
first_byte = chunk.getbyte(0)
|
|
115
|
-
chunk.bytes.all?(first_byte)
|
|
98
|
+
def write_empty_last_block
|
|
99
|
+
write_block_header(1, BLOCK_TYPE_RAW, 0)
|
|
116
100
|
end
|
|
117
101
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
# Bit 0: Last_Block (1 = last)
|
|
125
|
-
# Bits 1-2: Block_Type (1 = RLE)
|
|
126
|
-
# Bits 3-23: Block_Size
|
|
127
|
-
|
|
128
|
-
header = size << 3 # Block size in bits 3-23
|
|
129
|
-
header |= BLOCK_TYPE_RLE << 1 # Block type = 1 (RLE)
|
|
130
|
-
header |= 1 if is_last # Last block flag in bit 0
|
|
131
|
-
|
|
132
|
-
# Write 3 bytes little-endian
|
|
133
|
-
@output_stream.putc(header & 0xFF)
|
|
134
|
-
@output_stream.putc((header >> 8) & 0xFF)
|
|
135
|
-
@output_stream.putc((header >> 16) & 0xFF)
|
|
102
|
+
def write_chunk(chunk, is_last)
|
|
103
|
+
if chunk.bytesize >= 4 && rle_chunk?(chunk)
|
|
104
|
+
write_block_header(is_last ? 1 : 0, BLOCK_TYPE_RLE, chunk.bytesize)
|
|
105
|
+
@output_stream.putc(chunk.getbyte(0))
|
|
106
|
+
return
|
|
107
|
+
end
|
|
136
108
|
|
|
137
|
-
|
|
138
|
-
|
|
109
|
+
content = try_compressed(chunk)
|
|
110
|
+
if content.nil?
|
|
111
|
+
write_block_header(is_last ? 1 : 0, BLOCK_TYPE_RAW,
|
|
112
|
+
chunk.bytesize)
|
|
113
|
+
@output_stream.write(chunk)
|
|
114
|
+
else
|
|
115
|
+
write_block_header(is_last ? 1 : 0, BLOCK_TYPE_COMPRESSED,
|
|
116
|
+
content.bytesize)
|
|
117
|
+
@output_stream.write(content)
|
|
118
|
+
end
|
|
139
119
|
end
|
|
140
120
|
|
|
141
|
-
#
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
#
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
@output_stream.putc(header & 0xFF)
|
|
154
|
-
@output_stream.putc((header >> 8) & 0xFF)
|
|
155
|
-
@output_stream.putc((header >> 16) & 0xFF)
|
|
156
|
-
|
|
157
|
-
# Write block content
|
|
158
|
-
@output_stream.write(data)
|
|
121
|
+
# Build a Compressed_Block content: literals section plus an
|
|
122
|
+
# empty sequences section (nbSeq = 0). Returns nil when the
|
|
123
|
+
# result is not smaller than the raw chunk.
|
|
124
|
+
def try_compressed(chunk)
|
|
125
|
+
literals_section = LiteralsEncoder.encode(chunk)
|
|
126
|
+
# A single 0x00 byte: Number_of_Sequences = 0.
|
|
127
|
+
content = literals_section + "\x00".b
|
|
128
|
+
return nil if content.bytesize >= chunk.bytesize
|
|
129
|
+
|
|
130
|
+
content
|
|
131
|
+
rescue Omnizip::CompressionError
|
|
132
|
+
nil
|
|
159
133
|
end
|
|
160
134
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def write_compressed_block(data, is_last)
|
|
167
|
-
# Encode literals section
|
|
168
|
-
literals_section = LiteralsEncoder.encode(data, use_compression: true)
|
|
169
|
-
|
|
170
|
-
# Check if compression is beneficial
|
|
171
|
-
# Compressed block has overhead: block header (3) + literals header + sequences
|
|
172
|
-
# For now, we need sequences section too (even if empty)
|
|
173
|
-
sequences_section = encode_empty_sequences
|
|
174
|
-
|
|
175
|
-
block_content = literals_section + sequences_section
|
|
176
|
-
compressed_size = block_content.bytesize
|
|
177
|
-
|
|
178
|
-
# Only use compressed if it's smaller
|
|
179
|
-
if compressed_size >= data.bytesize
|
|
180
|
-
return false
|
|
181
|
-
end
|
|
135
|
+
def rle_chunk?(chunk)
|
|
136
|
+
first = chunk.getbyte(0)
|
|
137
|
+
idx = 1
|
|
138
|
+
while idx < chunk.bytesize
|
|
139
|
+
return false if chunk.getbyte(idx) != first
|
|
182
140
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
141
|
+
idx += 1
|
|
142
|
+
end
|
|
143
|
+
true
|
|
144
|
+
end
|
|
187
145
|
|
|
188
|
-
|
|
146
|
+
def write_block_header(last, type, size)
|
|
147
|
+
header = (last & 1) | (type << 1) | (size << 3)
|
|
189
148
|
@output_stream.putc(header & 0xFF)
|
|
190
149
|
@output_stream.putc((header >> 8) & 0xFF)
|
|
191
150
|
@output_stream.putc((header >> 16) & 0xFF)
|
|
192
|
-
|
|
193
|
-
# Write block content
|
|
194
|
-
@output_stream.write(block_content)
|
|
195
|
-
|
|
196
|
-
true
|
|
197
151
|
end
|
|
198
152
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def encode_empty_sequences
|
|
203
|
-
# Number of sequences = 0 (single byte 0x00)
|
|
204
|
-
"\x00"
|
|
153
|
+
def write_u16le(value)
|
|
154
|
+
@output_stream.putc(value & 0xFF)
|
|
155
|
+
@output_stream.putc((value >> 8) & 0xFF)
|
|
205
156
|
end
|
|
206
157
|
|
|
207
|
-
# Write unsigned 32-bit little-endian
|
|
208
158
|
def write_u32le(value)
|
|
209
159
|
@output_stream.putc(value & 0xFF)
|
|
210
160
|
@output_stream.putc((value >> 8) & 0xFF)
|
|
@@ -212,15 +162,8 @@ module Omnizip
|
|
|
212
162
|
@output_stream.putc((value >> 24) & 0xFF)
|
|
213
163
|
end
|
|
214
164
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
hash = seed
|
|
218
|
-
|
|
219
|
-
data.each_byte do |byte|
|
|
220
|
-
hash = ((hash << 5) + hash + byte) & 0xFFFFFFFF
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
hash
|
|
165
|
+
def write_u64le(value)
|
|
166
|
+
8.times { |i| @output_stream.putc((value >> (8 * i)) & 0xFF) }
|
|
224
167
|
end
|
|
225
168
|
end
|
|
226
169
|
end
|
|
@@ -60,6 +60,23 @@ module Omnizip
|
|
|
60
60
|
new(last_block, block_type, block_size, raw)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
# Parse block header from a byte string.
|
|
64
|
+
#
|
|
65
|
+
# @param data [String]
|
|
66
|
+
# @param pos [Integer] offset of the 3-byte header
|
|
67
|
+
# @return [Array(Block, Integer)] block and position after the
|
|
68
|
+
# header
|
|
69
|
+
def self.parse_from(data, pos)
|
|
70
|
+
raw = data.getbyte(pos) |
|
|
71
|
+
(data.getbyte(pos + 1) << 8) |
|
|
72
|
+
(data.getbyte(pos + 2) << 16)
|
|
73
|
+
last_block = raw.allbits?(0x01)
|
|
74
|
+
block_type = (raw >> 1) & 0x03
|
|
75
|
+
block_size = (raw >> 3) & 0x1FFFFF
|
|
76
|
+
|
|
77
|
+
[new(last_block, block_type, block_size, raw), pos + 3]
|
|
78
|
+
end
|
|
79
|
+
|
|
63
80
|
# Initialize with parsed values
|
|
64
81
|
#
|
|
65
82
|
# @param last_block [Boolean]
|
|
@@ -63,24 +63,41 @@ module Omnizip
|
|
|
63
63
|
# @param input [IO] Input stream positioned at frame header
|
|
64
64
|
# @return [Header] Parsed header
|
|
65
65
|
def self.parse(input)
|
|
66
|
-
|
|
66
|
+
parse_from(input.read, 0).first
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Parse frame header from a byte string.
|
|
70
|
+
#
|
|
71
|
+
# @param data [String]
|
|
72
|
+
# @param pos [Integer] offset of the descriptor byte
|
|
73
|
+
# @return [Array(Header, Integer)] header and position after
|
|
74
|
+
# the header
|
|
75
|
+
def self.parse_from(data, pos)
|
|
76
|
+
descriptor = data.getbyte(pos)
|
|
67
77
|
|
|
68
78
|
header = new(descriptor)
|
|
79
|
+
offset = pos + 1
|
|
69
80
|
|
|
70
|
-
# Parse optional fields based on descriptor bits
|
|
71
81
|
if header.window_descriptor?
|
|
72
|
-
header.
|
|
82
|
+
header.parse_window_descriptor_byte(data.getbyte(offset))
|
|
83
|
+
offset += 1
|
|
73
84
|
end
|
|
74
85
|
|
|
75
86
|
if header.dictionary_id?
|
|
76
|
-
header.
|
|
87
|
+
size = header.dictionary_id_size
|
|
88
|
+
bytes = data.byteslice(offset, size)
|
|
89
|
+
offset += size
|
|
90
|
+
header.assign_dictionary_id(bytes)
|
|
77
91
|
end
|
|
78
92
|
|
|
79
93
|
if header.content_size?
|
|
80
|
-
header.
|
|
94
|
+
size = header.content_size_size
|
|
95
|
+
bytes = data.byteslice(offset, size)
|
|
96
|
+
offset += size
|
|
97
|
+
header.assign_content_size(bytes)
|
|
81
98
|
end
|
|
82
99
|
|
|
83
|
-
header
|
|
100
|
+
[header, offset]
|
|
84
101
|
end
|
|
85
102
|
|
|
86
103
|
# Initialize with descriptor byte
|
|
@@ -96,6 +113,7 @@ module Omnizip
|
|
|
96
113
|
@dictionary_id_flag = descriptor & 0x03
|
|
97
114
|
|
|
98
115
|
@window_log = nil
|
|
116
|
+
@window_mantissa = 0
|
|
99
117
|
@dictionary_id = nil
|
|
100
118
|
@content_size = nil
|
|
101
119
|
@header_size = 1
|
|
@@ -165,53 +183,48 @@ module Omnizip
|
|
|
165
183
|
|
|
166
184
|
# Get window size
|
|
167
185
|
#
|
|
186
|
+
# windowAdd = (windowBase / 8) * Mantissa (RFC 8878
|
|
187
|
+
# §3.1.1.1.2); the mantissa occupies descriptor bits 0-2 and
|
|
188
|
+
# the exponent bits 3-7.
|
|
189
|
+
#
|
|
168
190
|
# @return [Integer, nil] Window size or nil if not applicable
|
|
169
191
|
def window_size
|
|
170
192
|
return nil unless @window_log
|
|
171
193
|
|
|
172
|
-
@window_log
|
|
173
|
-
|
|
174
|
-
(1 << @window_log) + (mantissa << (@window_log - 4))
|
|
194
|
+
window_base = 1 << @window_log
|
|
195
|
+
window_base + ((window_base / 8) * @window_mantissa)
|
|
175
196
|
end
|
|
176
197
|
|
|
177
198
|
# Parse window descriptor byte
|
|
178
|
-
def
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
byte & 0x07
|
|
182
|
-
@window_log = 10 + exponent
|
|
199
|
+
def parse_window_descriptor_byte(byte)
|
|
200
|
+
@window_mantissa = byte & 0x07
|
|
201
|
+
@window_log = 10 + ((byte >> 3) & 0x1F)
|
|
183
202
|
@header_size += 1
|
|
184
203
|
end
|
|
185
204
|
|
|
186
|
-
#
|
|
187
|
-
def
|
|
188
|
-
|
|
189
|
-
bytes = input.read(size)
|
|
190
|
-
|
|
191
|
-
@dictionary_id = case size
|
|
205
|
+
# Assign the dictionary ID from its wire bytes.
|
|
206
|
+
def assign_dictionary_id(bytes)
|
|
207
|
+
@dictionary_id = case bytes.bytesize
|
|
192
208
|
when 1 then bytes.ord
|
|
193
209
|
when 2 then bytes.unpack1("v")
|
|
194
210
|
when 4 then bytes.unpack1("V")
|
|
195
211
|
end
|
|
196
212
|
|
|
197
|
-
@header_size +=
|
|
213
|
+
@header_size += bytes.bytesize
|
|
198
214
|
end
|
|
199
215
|
|
|
200
|
-
#
|
|
201
|
-
def
|
|
202
|
-
|
|
203
|
-
bytes = input.read(size)
|
|
204
|
-
|
|
205
|
-
@content_size = case size
|
|
216
|
+
# Assign the content size from its wire bytes.
|
|
217
|
+
def assign_content_size(bytes)
|
|
218
|
+
@content_size = case bytes.bytesize
|
|
206
219
|
when 1 then bytes.ord
|
|
207
|
-
when 2 then bytes.unpack1("v")
|
|
220
|
+
when 2 then bytes.unpack1("v") + 256
|
|
208
221
|
when 4 then bytes.unpack1("V")
|
|
209
222
|
when 8
|
|
210
223
|
low, high = bytes.unpack("VV")
|
|
211
224
|
low + (high << 32)
|
|
212
225
|
end
|
|
213
226
|
|
|
214
|
-
@header_size +=
|
|
227
|
+
@header_size += bytes.bytesize
|
|
215
228
|
end
|
|
216
229
|
end
|
|
217
230
|
end
|