ruby-bzs 1.0.0

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.
@@ -0,0 +1,31 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #if !defined(BZS_EXT_STREAM_DECOMPRESSOR_H)
5
+ #define BZS_EXT_STREAM_DECOMPRESSOR_H
6
+
7
+ #include <bzlib.h>
8
+ #include <stdbool.h>
9
+
10
+ #include "bzs_ext/common.h"
11
+ #include "ruby.h"
12
+
13
+ typedef struct
14
+ {
15
+ bz_stream* stream_ptr;
16
+ bzs_ext_byte_t* destination_buffer;
17
+ size_t destination_buffer_length;
18
+ bzs_ext_byte_t* remaining_destination_buffer;
19
+ size_t remaining_destination_buffer_length;
20
+ bool gvl;
21
+ } bzs_ext_decompressor_t;
22
+
23
+ VALUE bzs_ext_allocate_decompressor(VALUE klass);
24
+ VALUE bzs_ext_initialize_decompressor(VALUE self, VALUE options);
25
+ VALUE bzs_ext_decompress(VALUE self, VALUE source);
26
+ VALUE bzs_ext_decompressor_read_result(VALUE self);
27
+ VALUE bzs_ext_decompressor_close(VALUE self);
28
+
29
+ void bzs_ext_decompressor_exports(VALUE root_module);
30
+
31
+ #endif // BZS_EXT_STREAM_DECOMPRESSOR_H
@@ -0,0 +1,340 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #include "bzs_ext/string.h"
5
+
6
+ #include <bzlib.h>
7
+
8
+ #include "bzs_ext/buffer.h"
9
+ #include "bzs_ext/common.h"
10
+ #include "bzs_ext/error.h"
11
+ #include "bzs_ext/gvl.h"
12
+ #include "bzs_ext/macro.h"
13
+ #include "bzs_ext/option.h"
14
+ #include "bzs_ext/utils.h"
15
+
16
+ // -- buffer --
17
+
18
+ static inline bzs_ext_result_t increase_destination_buffer(
19
+ VALUE destination_value,
20
+ size_t destination_length,
21
+ size_t* remaining_destination_buffer_length_ptr,
22
+ size_t destination_buffer_length)
23
+ {
24
+ if (*remaining_destination_buffer_length_ptr == destination_buffer_length) {
25
+ // We want to write more data at once, than buffer has.
26
+ return BZS_EXT_ERROR_NOT_ENOUGH_DESTINATION_BUFFER;
27
+ }
28
+
29
+ int exception;
30
+
31
+ BZS_EXT_RESIZE_STRING_BUFFER(destination_value, destination_length + destination_buffer_length, exception);
32
+ if (exception != 0) {
33
+ return BZS_EXT_ERROR_ALLOCATE_FAILED;
34
+ }
35
+
36
+ *remaining_destination_buffer_length_ptr = destination_buffer_length;
37
+
38
+ return 0;
39
+ }
40
+
41
+ // -- compress --
42
+
43
+ typedef struct
44
+ {
45
+ bz_stream* stream_ptr;
46
+ int stream_action;
47
+ bzs_ext_byte_t** remaining_source_ptr;
48
+ size_t* remaining_source_length_ptr;
49
+ bzs_ext_byte_t* remaining_destination_buffer;
50
+ size_t* remaining_destination_buffer_length_ptr;
51
+ bzs_result_t result;
52
+ } compress_args_t;
53
+
54
+ static inline void* compress_wrapper(void* data)
55
+ {
56
+ compress_args_t* args = data;
57
+
58
+ args->stream_ptr->next_in = (char*) *args->remaining_source_ptr;
59
+ args->stream_ptr->avail_in = bzs_consume_size(*args->remaining_source_length_ptr);
60
+ args->stream_ptr->next_out = (char*) args->remaining_destination_buffer;
61
+ args->stream_ptr->avail_out = bzs_consume_size(*args->remaining_destination_buffer_length_ptr);
62
+
63
+ args->result = BZ2_bzCompress(args->stream_ptr, args->stream_action);
64
+
65
+ *args->remaining_source_ptr = (bzs_ext_byte_t*) args->stream_ptr->next_in;
66
+ *args->remaining_source_length_ptr = args->stream_ptr->avail_in;
67
+ *args->remaining_destination_buffer_length_ptr = args->stream_ptr->avail_out;
68
+
69
+ return NULL;
70
+ }
71
+
72
+ #define BUFFERED_COMPRESS(gvl, args, RUN_OK) \
73
+ while (true) { \
74
+ bzs_ext_byte_t* remaining_destination_buffer = \
75
+ (bzs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length; \
76
+ size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length; \
77
+ \
78
+ args.remaining_destination_buffer = remaining_destination_buffer; \
79
+ args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length; \
80
+ \
81
+ BZS_EXT_GVL_WRAP(gvl, compress_wrapper, &args); \
82
+ if (args.result != RUN_OK && args.result != BZ_PARAM_ERROR && args.result != BZ_STREAM_END) { \
83
+ return bzs_ext_get_error(args.result); \
84
+ } \
85
+ \
86
+ destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length; \
87
+ \
88
+ if (args.result == BZ_STREAM_END) { \
89
+ break; \
90
+ } \
91
+ \
92
+ if (remaining_source_length != 0 || remaining_destination_buffer_length == 0) { \
93
+ ext_result = increase_destination_buffer( \
94
+ destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length); \
95
+ \
96
+ if (ext_result != 0) { \
97
+ return ext_result; \
98
+ } \
99
+ \
100
+ continue; \
101
+ } \
102
+ \
103
+ break; \
104
+ }
105
+
106
+ static inline bzs_ext_result_t compress(
107
+ bz_stream* stream_ptr,
108
+ const char* source,
109
+ size_t source_length,
110
+ VALUE destination_value,
111
+ size_t destination_buffer_length,
112
+ bool gvl)
113
+ {
114
+ bzs_ext_result_t ext_result;
115
+ bzs_ext_byte_t* remaining_source = (bzs_ext_byte_t*) source;
116
+ size_t remaining_source_length = source_length;
117
+ size_t destination_length = 0;
118
+ size_t remaining_destination_buffer_length = destination_buffer_length;
119
+
120
+ compress_args_t run_args = {
121
+ .stream_ptr = stream_ptr,
122
+ .stream_action = BZ_RUN,
123
+ .remaining_source_ptr = &remaining_source,
124
+ .remaining_source_length_ptr = &remaining_source_length};
125
+ BUFFERED_COMPRESS(gvl, run_args, BZ_RUN_OK);
126
+
127
+ compress_args_t finish_args = {
128
+ .stream_ptr = stream_ptr,
129
+ .stream_action = BZ_FINISH,
130
+ .remaining_source_ptr = &remaining_source,
131
+ .remaining_source_length_ptr = &remaining_source_length};
132
+ BUFFERED_COMPRESS(gvl, finish_args, BZ_FINISH_OK);
133
+
134
+ int exception;
135
+
136
+ BZS_EXT_RESIZE_STRING_BUFFER(destination_value, destination_length, exception);
137
+ if (exception != 0) {
138
+ return BZS_EXT_ERROR_ALLOCATE_FAILED;
139
+ }
140
+
141
+ return 0;
142
+ }
143
+
144
+ VALUE bzs_ext_compress_string(VALUE BZS_EXT_UNUSED(self), VALUE source_value, VALUE options)
145
+ {
146
+ Check_Type(source_value, T_STRING);
147
+ Check_Type(options, T_HASH);
148
+ BZS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
149
+ BZS_EXT_GET_BOOL_OPTION(options, gvl);
150
+ BZS_EXT_RESOLVE_COMPRESSOR_OPTIONS(options);
151
+
152
+ bz_stream stream = {
153
+ .bzalloc = NULL,
154
+ .bzfree = NULL,
155
+ .opaque = NULL,
156
+ };
157
+
158
+ bzs_result_t result = BZ2_bzCompressInit(&stream, block_size, verbosity, work_factor);
159
+ if (result != BZ_OK) {
160
+ bzs_ext_raise_error(bzs_ext_get_error(result));
161
+ }
162
+
163
+ if (destination_buffer_length == 0) {
164
+ destination_buffer_length = BZS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR;
165
+ }
166
+
167
+ int exception;
168
+
169
+ BZS_EXT_CREATE_STRING_BUFFER(destination_value, destination_buffer_length, exception);
170
+ if (exception != 0) {
171
+ BZ2_bzCompressEnd(&stream);
172
+ bzs_ext_raise_error(BZS_EXT_ERROR_ALLOCATE_FAILED);
173
+ }
174
+
175
+ const char* source = RSTRING_PTR(source_value);
176
+ size_t source_length = RSTRING_LEN(source_value);
177
+
178
+ bzs_ext_result_t ext_result =
179
+ compress(&stream, source, source_length, destination_value, destination_buffer_length, gvl);
180
+
181
+ result = BZ2_bzCompressEnd(&stream);
182
+ if (result != BZ_OK) {
183
+ ext_result = bzs_ext_get_error(result);
184
+ }
185
+
186
+ if (ext_result != 0) {
187
+ bzs_ext_raise_error(ext_result);
188
+ }
189
+
190
+ return destination_value;
191
+ }
192
+
193
+ // -- decompress --
194
+
195
+ typedef struct
196
+ {
197
+ bz_stream* stream_ptr;
198
+ bzs_ext_byte_t** remaining_source_ptr;
199
+ size_t* remaining_source_length_ptr;
200
+ bzs_ext_byte_t* remaining_destination_buffer;
201
+ size_t* remaining_destination_buffer_length_ptr;
202
+ bzs_result_t result;
203
+ } decompress_args_t;
204
+
205
+ static inline void* decompress_wrapper(void* data)
206
+ {
207
+ decompress_args_t* args = data;
208
+
209
+ args->stream_ptr->next_in = (char*) *args->remaining_source_ptr;
210
+ args->stream_ptr->avail_in = bzs_consume_size(*args->remaining_source_length_ptr);
211
+ args->stream_ptr->next_out = (char*) args->remaining_destination_buffer;
212
+ args->stream_ptr->avail_out = bzs_consume_size(*args->remaining_destination_buffer_length_ptr);
213
+
214
+ args->result = BZ2_bzDecompress(args->stream_ptr);
215
+
216
+ *args->remaining_source_ptr = (bzs_ext_byte_t*) args->stream_ptr->next_in;
217
+ *args->remaining_source_length_ptr = args->stream_ptr->avail_in;
218
+ *args->remaining_destination_buffer_length_ptr = args->stream_ptr->avail_out;
219
+
220
+ return NULL;
221
+ }
222
+
223
+ static inline bzs_ext_result_t decompress(
224
+ bz_stream* stream_ptr,
225
+ const char* source,
226
+ size_t source_length,
227
+ VALUE destination_value,
228
+ size_t destination_buffer_length,
229
+ bool gvl)
230
+ {
231
+ bzs_ext_result_t ext_result;
232
+ bzs_ext_byte_t* remaining_source = (bzs_ext_byte_t*) source;
233
+ size_t remaining_source_length = source_length;
234
+ size_t destination_length = 0;
235
+ size_t remaining_destination_buffer_length = destination_buffer_length;
236
+
237
+ decompress_args_t args = {
238
+ .stream_ptr = stream_ptr,
239
+ .remaining_source_ptr = &remaining_source,
240
+ .remaining_source_length_ptr = &remaining_source_length};
241
+
242
+ while (true) {
243
+ bzs_ext_byte_t* remaining_destination_buffer =
244
+ (bzs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length;
245
+ size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
246
+
247
+ args.remaining_destination_buffer = remaining_destination_buffer;
248
+ args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
249
+
250
+ BZS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
251
+ if (args.result != BZ_OK && args.result != BZ_PARAM_ERROR && args.result != BZ_STREAM_END) {
252
+ return bzs_ext_get_error(args.result);
253
+ }
254
+
255
+ destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length;
256
+
257
+ if (args.result == BZ_STREAM_END) {
258
+ break;
259
+ }
260
+
261
+ if (remaining_source_length != 0 || remaining_destination_buffer_length == 0) {
262
+ ext_result = increase_destination_buffer(
263
+ destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length);
264
+
265
+ if (ext_result != 0) {
266
+ return ext_result;
267
+ }
268
+
269
+ continue;
270
+ }
271
+
272
+ break;
273
+ }
274
+
275
+ int exception;
276
+
277
+ BZS_EXT_RESIZE_STRING_BUFFER(destination_value, destination_length, exception);
278
+ if (exception != 0) {
279
+ return BZS_EXT_ERROR_ALLOCATE_FAILED;
280
+ }
281
+
282
+ return 0;
283
+ }
284
+
285
+ VALUE bzs_ext_decompress_string(VALUE BZS_EXT_UNUSED(self), VALUE source_value, VALUE options)
286
+ {
287
+ Check_Type(source_value, T_STRING);
288
+ Check_Type(options, T_HASH);
289
+ BZS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
290
+ BZS_EXT_GET_BOOL_OPTION(options, gvl);
291
+ BZS_EXT_RESOLVE_DECOMPRESSOR_OPTIONS(options);
292
+
293
+ bz_stream stream = {
294
+ .bzalloc = NULL,
295
+ .bzfree = NULL,
296
+ .opaque = NULL,
297
+ };
298
+
299
+ bzs_result_t result = BZ2_bzDecompressInit(&stream, verbosity, small);
300
+ if (result != BZ_OK) {
301
+ bzs_ext_raise_error(bzs_ext_get_error(result));
302
+ }
303
+
304
+ if (destination_buffer_length == 0) {
305
+ destination_buffer_length = BZS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR;
306
+ }
307
+
308
+ int exception;
309
+
310
+ BZS_EXT_CREATE_STRING_BUFFER(destination_value, destination_buffer_length, exception);
311
+ if (exception != 0) {
312
+ BZ2_bzDecompressEnd(&stream);
313
+ bzs_ext_raise_error(BZS_EXT_ERROR_ALLOCATE_FAILED);
314
+ }
315
+
316
+ const char* source = RSTRING_PTR(source_value);
317
+ size_t source_length = RSTRING_LEN(source_value);
318
+
319
+ bzs_ext_result_t ext_result =
320
+ decompress(&stream, source, source_length, destination_value, destination_buffer_length, gvl);
321
+
322
+ result = BZ2_bzDecompressEnd(&stream);
323
+ if (result != BZ_OK) {
324
+ ext_result = bzs_ext_get_error(result);
325
+ }
326
+
327
+ if (ext_result != 0) {
328
+ bzs_ext_raise_error(ext_result);
329
+ }
330
+
331
+ return destination_value;
332
+ }
333
+
334
+ // -- exports --
335
+
336
+ void bzs_ext_string_exports(VALUE root_module)
337
+ {
338
+ rb_define_module_function(root_module, "_native_compress_string", RUBY_METHOD_FUNC(bzs_ext_compress_string), 2);
339
+ rb_define_module_function(root_module, "_native_decompress_string", RUBY_METHOD_FUNC(bzs_ext_decompress_string), 2);
340
+ }
@@ -0,0 +1,14 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #if !defined(BZS_EXT_STRING_H)
5
+ #define BZS_EXT_STRING_H
6
+
7
+ #include "ruby.h"
8
+
9
+ VALUE bzs_ext_compress_string(VALUE self, VALUE source, VALUE options);
10
+ VALUE bzs_ext_decompress_string(VALUE self, VALUE source, VALUE options);
11
+
12
+ void bzs_ext_string_exports(VALUE root_module);
13
+
14
+ #endif // BZS_EXT_STRING_H
@@ -0,0 +1,15 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #include "utils.h"
5
+
6
+ #include <limits.h>
7
+
8
+ unsigned int bzs_consume_size(size_t size)
9
+ {
10
+ if (size > UINT_MAX) {
11
+ return UINT_MAX;
12
+ } else {
13
+ return (unsigned int) size;
14
+ }
15
+ }
@@ -0,0 +1,13 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #if !defined(BZS_EXT_UTILS_H)
5
+ #define BZS_EXT_UTILS_H
6
+
7
+ #include <stdlib.h>
8
+
9
+ // Bzip2 size type may be limited to unsigned int.
10
+ // We need to prevent overflow by consuming max available unsigned int value.
11
+ unsigned int bzs_consume_size(size_t size);
12
+
13
+ #endif // BZS_EXT_UTILS_H
data/ext/extconf.rb ADDED
@@ -0,0 +1,94 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "mkmf"
5
+
6
+ have_func "rb_thread_call_without_gvl", "ruby/thread.h"
7
+
8
+ def require_header(name, constants: [], types: [])
9
+ abort "Can't find #{name} header" unless find_header name
10
+
11
+ constants.each do |constant|
12
+ abort "Can't find #{constant} constant in #{name} header" unless have_const constant, name
13
+ end
14
+
15
+ types.each do |type|
16
+ abort "Can't find #{type} type in #{name} header" unless find_type type, nil, name
17
+ end
18
+ end
19
+
20
+ require_header(
21
+ "bzlib.h",
22
+ :constants => %w[
23
+ BZ_RUN
24
+ BZ_RUN_OK
25
+ BZ_FINISH
26
+ BZ_FINISH_OK
27
+ BZ_FLUSH
28
+ BZ_FLUSH_OK
29
+ BZ_OK
30
+ BZ_PARAM_ERROR
31
+ BZ_STREAM_END
32
+ BZ_MEM_ERROR
33
+ BZ_DATA_ERROR
34
+ BZ_DATA_ERROR_MAGIC
35
+ BZ_UNEXPECTED_EOF
36
+ ],
37
+ :types => %w[
38
+ bz_stream
39
+ ]
40
+ )
41
+
42
+ def require_library(name, functions)
43
+ functions.each do |function|
44
+ abort "Can't find #{function} function in #{name} library" unless find_library name, function
45
+ end
46
+ end
47
+
48
+ require_library(
49
+ "bz2",
50
+ %w[
51
+ BZ2_bzCompressInit
52
+ BZ2_bzCompress
53
+ BZ2_bzCompressEnd
54
+ BZ2_bzDecompressInit
55
+ BZ2_bzDecompress
56
+ BZ2_bzDecompressEnd
57
+ BZ2_bzlibVersion
58
+ ]
59
+ )
60
+
61
+ extension_name = "bzs_ext".freeze
62
+ dir_config extension_name
63
+
64
+ # rubocop:disable Style/GlobalVars
65
+ $srcs = %w[
66
+ stream/compressor
67
+ stream/decompressor
68
+ buffer
69
+ error
70
+ io
71
+ main
72
+ option
73
+ string
74
+ utils
75
+ ]
76
+ .map { |name| "src/#{extension_name}/#{name}.c" }
77
+ .freeze
78
+
79
+ # Removing library duplicates.
80
+ $libs = $libs.split(%r{\s})
81
+ .reject(&:empty?)
82
+ .sort
83
+ .uniq
84
+ .join " "
85
+
86
+ if ENV["CI"]
87
+ $CFLAGS << " --coverage"
88
+ $LDFLAGS << " --coverage"
89
+ end
90
+
91
+ $VPATH << "$(srcdir)/#{extension_name}:$(srcdir)/#{extension_name}/stream"
92
+ # rubocop:enable Style/GlobalVars
93
+
94
+ create_makefile extension_name
data/lib/bzs/error.rb ADDED
@@ -0,0 +1,26 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "adsp"
5
+
6
+ module BZS
7
+ class BaseError < ::StandardError; end
8
+
9
+ class AllocateError < BaseError; end
10
+
11
+ class NotEnoughSourceBufferError < BaseError; end
12
+ class NotEnoughDestinationBufferError < BaseError; end
13
+ class DecompressorCorruptedSourceError < BaseError; end
14
+
15
+ class AccessIOError < BaseError; end
16
+ class ReadIOError < BaseError; end
17
+ class WriteIOError < BaseError; end
18
+
19
+ ValidateError = ADSP::ValidateError
20
+
21
+ NotEnoughDestinationError = ADSP::NotEnoughDestinationError
22
+ UsedAfterCloseError = ADSP::UsedAfterCloseError
23
+
24
+ NotImplementedError = ADSP::NotImplementedError
25
+ UnexpectedError = ADSP::UnexpectedError
26
+ end
data/lib/bzs/file.rb ADDED
@@ -0,0 +1,25 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "adsp/file"
5
+ require "bzs_ext"
6
+
7
+ require_relative "option"
8
+
9
+ module BZS
10
+ # BZS::File class.
11
+ class File < ADSP::File
12
+ # Current option class.
13
+ Option = BZS::Option
14
+
15
+ # Bypass native compress.
16
+ def self.native_compress_io(*args)
17
+ BZS._native_compress_io(*args)
18
+ end
19
+
20
+ # Bypass native decompress.
21
+ def self.native_decompress_io(*args)
22
+ BZS._native_decompress_io(*args)
23
+ end
24
+ end
25
+ end
data/lib/bzs/option.rb ADDED
@@ -0,0 +1,101 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "bzs_ext"
5
+
6
+ require_relative "error"
7
+ require_relative "validation"
8
+
9
+ module BZS
10
+ # BZS::Option module.
11
+ module Option
12
+ # Current default buffer length.
13
+ DEFAULT_BUFFER_LENGTH = 0
14
+
15
+ # Current compressor defaults.
16
+ COMPRESSOR_DEFAULTS = {
17
+ # Enables global VM lock where possible.
18
+ :gvl => false,
19
+ # Block size to be used for compression.
20
+ :block_size => nil,
21
+ # Controls threshold for switching from standard to fallback algorithm.
22
+ :work_factor => nil,
23
+ # Disables bzip2 library logging.
24
+ :quiet => nil
25
+ }
26
+ .freeze
27
+
28
+ # Current decompressor defaults.
29
+ DECOMPRESSOR_DEFAULTS = {
30
+ # Enables global VM lock where possible.
31
+ :gvl => false,
32
+ # Enables alternative decompression algorithm with less memory.
33
+ :small => nil,
34
+ # Disables bzip2 library logging.
35
+ :quiet => nil
36
+ }
37
+ .freeze
38
+
39
+ # Processes compressor +options+ and +buffer_length_names+.
40
+ # Option: +:source_buffer_length+ source buffer length.
41
+ # Option: +:destination_buffer_length+ destination buffer length.
42
+ # Option: +:gvl+ enables global VM lock where possible.
43
+ # Option: +:block_size+ block size to be used for compression.
44
+ # Option: +:work_factor+ controls threshold for switching from standard to fallback algorithm.
45
+ # Option: +:quiet+ disables bzip2 library logging.
46
+ # Returns processed compressor options.
47
+ def self.get_compressor_options(options, buffer_length_names)
48
+ Validation.validate_hash options
49
+
50
+ buffer_length_defaults = buffer_length_names.each_with_object({}) do |name, defaults|
51
+ defaults[name] = DEFAULT_BUFFER_LENGTH
52
+ end
53
+
54
+ options = COMPRESSOR_DEFAULTS.merge(buffer_length_defaults).merge options
55
+
56
+ buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
57
+
58
+ Validation.validate_bool options[:gvl]
59
+
60
+ block_size = options[:block_size]
61
+ Validation.validate_not_negative_integer block_size unless block_size.nil?
62
+
63
+ work_factor = options[:work_factor]
64
+ Validation.validate_not_negative_integer work_factor unless work_factor.nil?
65
+
66
+ quiet = options[:quiet]
67
+ Validation.validate_bool quiet unless quiet.nil?
68
+
69
+ options
70
+ end
71
+
72
+ # Processes decompressor +options+ and +buffer_length_names+.
73
+ # Option: +:source_buffer_length+ source buffer length.
74
+ # Option: +:destination_buffer_length+ destination buffer length.
75
+ # Option: +:gvl+ enables global VM lock where possible.
76
+ # Option: +:small+ enables alternative decompression algorithm with less memory.
77
+ # Option: +:quiet+ disables bzip2 library logging.
78
+ # Returns processed decompressor options.
79
+ def self.get_decompressor_options(options, buffer_length_names)
80
+ Validation.validate_hash options
81
+
82
+ buffer_length_defaults = buffer_length_names.each_with_object({}) do |name, defaults|
83
+ defaults[name] = DEFAULT_BUFFER_LENGTH
84
+ end
85
+
86
+ options = DECOMPRESSOR_DEFAULTS.merge(buffer_length_defaults).merge options
87
+
88
+ buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
89
+
90
+ Validation.validate_bool options[:gvl]
91
+
92
+ small = options[:small]
93
+ Validation.validate_bool small unless small.nil?
94
+
95
+ quiet = options[:quiet]
96
+ Validation.validate_bool quiet unless quiet.nil?
97
+
98
+ options
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,22 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "adsp/stream/raw/compressor"
5
+ require "bzs_ext"
6
+
7
+ require_relative "../../option"
8
+
9
+ module BZS
10
+ module Stream
11
+ module Raw
12
+ # BZS::Stream::Raw::Compressor class.
13
+ class Compressor < ADSP::Stream::Raw::Compressor
14
+ # Current native compressor class.
15
+ NativeCompressor = Stream::NativeCompressor
16
+
17
+ # Current option class.
18
+ Option = BZS::Option
19
+ end
20
+ end
21
+ end
22
+ end