ruby-brs 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 779dc2709fa1dc4c1316cafb41ec7ca289ddab6e3e93302c8c9d730d5e13062c
4
+ data.tar.gz: b9e44118ae67ccc3ddc80a4976c946ef1b4d0801192b5b2f7f286bbf7b6f1446
5
+ SHA512:
6
+ metadata.gz: fd2f3127fa61d8e5d1523c331edbb96823976622d81ba61ff4d10965ed9f536773a2abbea59c3fd1a03b9d6df9b4fbe9662a0d47cdaed5aa19e481544cc9952a
7
+ data.tar.gz: d487532c19995e7307f68b1b5ccc091e9445e02b8a53c3c9039765e8fbb6dd11960563d6860aaba236dc7b7b424674d12f471163cd52940511dbd4803799a250
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ Andrew Aladjev
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 AUTHORS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,339 @@
1
+ # Ruby bindings for brotli library
2
+
3
+ [![Travis build status](https://travis-ci.org/andrew-aladev/ruby-brs.svg?branch=master)](https://travis-ci.org/andrew-aladev/ruby-brs)
4
+ [![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/andrew-aladev/ruby-brs?branch=master&svg=true)](https://ci.appveyor.com/project/andrew-aladev/ruby-brs/branch/master)
5
+
6
+ See [brotli library](https://github.com/google/brotli).
7
+
8
+ ## Installation
9
+
10
+ Please install brotli library first.
11
+
12
+ ```sh
13
+ gem install ruby-brs
14
+ ```
15
+
16
+ You can build it from source.
17
+
18
+ ```sh
19
+ rake gem
20
+ gem install pkg/ruby-brs-*.gem
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ There are simple APIs: `String` and `File`. Also you can use generic streaming API: `Stream::Writer` and `Stream::Reader`.
26
+
27
+ ```ruby
28
+ require "brs"
29
+
30
+ data = BRS::String.compress "sample string"
31
+ puts BRS::String.decompress(data)
32
+
33
+ BRS::File.compress "file.txt", "file.txt.br"
34
+ BRS::File.decompress "file.txt.br", "file.txt"
35
+
36
+ BRS::Stream::Writer.open("file.txt.br") { |writer| writer << "sample string" }
37
+ puts BRS::Stream::Reader.open("file.txt.br") { |reader| reader.read }
38
+ ```
39
+
40
+ You can create and read `tar.br` archives with `minitar` for example.
41
+
42
+ ```ruby
43
+ require "brs"
44
+ require "minitar"
45
+
46
+ BRS::Stream::Writer.open "file.tar.br" do |writer|
47
+ Minitar::Writer.open writer do |tar|
48
+ tar.add_file_simple "file", :data => "sample string"
49
+ end
50
+ end
51
+
52
+ BRS::Stream::Reader.open "file.tar.br" do |reader|
53
+ Minitar::Reader.open reader do |tar|
54
+ tar.each_entry do |entry|
55
+ puts entry.name
56
+ puts entry.read
57
+ end
58
+ end
59
+ end
60
+ ```
61
+
62
+ ## Options
63
+
64
+ Each API supports several options:
65
+
66
+ ```
67
+ :source_buffer_length
68
+ :destination_buffer_length
69
+ ```
70
+
71
+ There are internal buffers for compressed and decompressed data.
72
+ For example you want to use 1 KB as source buffer length for compressor - please use 256 B as destination buffer length.
73
+ You want to use 256 B as source buffer length for decompressor - please use 1 KB as destination buffer length.
74
+
75
+ Values: 0 - infinity, default value: 0.
76
+ 0 means automatic buffer length selection.
77
+
78
+ ```
79
+ :mode
80
+ ```
81
+
82
+ Values: [`:text`, `:font`, `:generic`], default value: `:generic`.
83
+
84
+ ```
85
+ :quality
86
+ ```
87
+
88
+ Values: 0 - 11, default value: 11.
89
+
90
+ ```
91
+ :lgwin
92
+ ```
93
+
94
+ Values: 10 - 24, default value: 22.
95
+
96
+ ```
97
+ :lgblock
98
+ ```
99
+
100
+ Values: 16 - 24, default value: none.
101
+
102
+ ```
103
+ :disable_literal_context_modeling
104
+ ```
105
+
106
+ Values: true/false, default value: false.
107
+
108
+ ```
109
+ :disable_ring_buffer_reallocation
110
+ ```
111
+
112
+ Values: true/false, default value: false.
113
+
114
+ ```
115
+ :size_hint
116
+ ```
117
+
118
+ Values: 0 - infinity, default value: 0.
119
+
120
+ ```
121
+ :large_window
122
+ ```
123
+
124
+ Values: true/false, default value: false.
125
+
126
+ Please read brotli docs for more info about options.
127
+
128
+ Possible compressor options:
129
+ ```
130
+ :mode
131
+ :quality
132
+ :lgwin
133
+ :lgblock
134
+ :disable_literal_context_modeling
135
+ :size_hint
136
+ :large_window
137
+ ```
138
+
139
+ Possible decompressor options:
140
+ ```
141
+ :disable_ring_buffer_reallocation
142
+ :large_window
143
+ ```
144
+
145
+ Example:
146
+
147
+ ```ruby
148
+ require "brs"
149
+
150
+ data = BRS::String.compress "sample string", :quality => 5
151
+ puts BRS::String.decompress(data, :disable_ring_buffer_reallocation => true)
152
+ ```
153
+
154
+ Default options are compatible with HTTP (`Content-Encoding: br`):
155
+
156
+ ```ruby
157
+ require "brs"
158
+ require "sinatra"
159
+
160
+ get "/" do
161
+ headers["Content-Encoding"] = "br"
162
+ BRS::String.compress "sample string"
163
+ end
164
+ ```
165
+
166
+ ## String
167
+
168
+ String maintains destination buffer only, so it accepts `destination_buffer_length` option only.
169
+
170
+ ```
171
+ ::compress(source, options = {})
172
+ ::decompress(source, options = {})
173
+ ```
174
+
175
+ `source` is a source string.
176
+
177
+ ## File
178
+
179
+ File maintains both source and destination buffers, it accepts both `source_buffer_length` and `destination_buffer_length` options.
180
+
181
+ ```
182
+ ::compress(source, destination, options = {})
183
+ ::decompress(source, destination, options = {})
184
+ ```
185
+
186
+ `source` and `destination` are file pathes.
187
+
188
+ ## Stream::Writer
189
+
190
+ Its behaviour is similar to builtin [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.6.1/libdoc/zlib/rdoc/Zlib/GzipWriter.html).
191
+
192
+ Writer maintains destination buffer only, so it accepts `destination_buffer_length` option only.
193
+
194
+ ```
195
+ ::open(file_path, options = {}, :external_encoding => nil, :transcode_options => {}, &block)
196
+ ```
197
+
198
+ Open file path and create stream writer associated with opened file.
199
+ Data will be transcoded to `:external_encoding` using `:transcode_options` before compressing.
200
+
201
+ ```
202
+ ::new(destination_io, options = {}, :external_encoding => nil, :transcode_options => {})
203
+ ```
204
+
205
+ Create stream writer associated with destination io.
206
+ Data will be transcoded to `:external_encoding` using `:transcode_options` before compressing.
207
+
208
+ ```
209
+ #set_encoding(external_encoding, nil, transcode_options)
210
+ ```
211
+
212
+ Set another encodings, `nil` is just for compatibility with `IO`.
213
+
214
+ ```
215
+ #io
216
+ #to_io
217
+ #stat
218
+ #external_encoding
219
+ #transcode_options
220
+ #pos
221
+ #tell
222
+ ```
223
+
224
+ See [`IO`](https://ruby-doc.org/core-2.6.1/IO.html) docs.
225
+
226
+ ```
227
+ #write(*objects)
228
+ #flush
229
+ #rewind
230
+ #close
231
+ #closed?
232
+ ```
233
+
234
+ See [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.6.1/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
235
+
236
+ ```
237
+ #write_nonblock(object, *options)
238
+ #flush_nonblock(*options)
239
+ #rewind_nonblock(*options)
240
+ #close_nonblock(*options)
241
+ ```
242
+
243
+ Special asynchronous methods missing in `Zlib::GzipWriter`.
244
+ `rewind` wants to `close`, `close` wants to `write` something and `flush`, `flush` want to `write` something.
245
+ So it is possible to have asynchronous variants for these synchronous methods.
246
+ Behaviour is the same as `IO#write_nonblock` method.
247
+
248
+ ```
249
+ #<<(object)
250
+ #print(*objects)
251
+ #printf(*args)
252
+ #putc(object, encoding: ::Encoding::BINARY)
253
+ #puts(*objects)
254
+ ```
255
+
256
+ Typical helpers, see [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.6.1/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
257
+
258
+ ## Stream::Reader
259
+
260
+ Its behaviour is similar to builtin [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.6.1/libdoc/zlib/rdoc/Zlib/GzipReader.html).
261
+
262
+ Reader maintains both source and destination buffers, it accepts both `source_buffer_length` and `destination_buffer_length` options.
263
+
264
+ ```
265
+ ::open(file_path, options = {}, :external_encoding => nil, :internal_encoding => nil, :transcode_options => {}, &block)
266
+ ```
267
+
268
+ Open file path and create stream reader associated with opened file.
269
+ Data will be force encoded to `:external_encoding` and transcoded to `:internal_encoding` using `:transcode_options` after decompressing.
270
+
271
+ ```
272
+ ::new(source_io, options = {}, :external_encoding => nil, :internal_encoding => nil, :transcode_options => {})
273
+ ```
274
+
275
+ Create stream reader associated with source io.
276
+ Data will be force encoded to `:external_encoding` and transcoded to `:internal_encoding` using `:transcode_options` after decompressing.
277
+
278
+ ```
279
+ #set_encoding(external_encoding, internal_encoding, transcode_options)
280
+ ```
281
+
282
+ Set another encodings.
283
+
284
+ ```
285
+ #io
286
+ #to_io
287
+ #stat
288
+ #external_encoding
289
+ #internal_encoding
290
+ #transcode_options
291
+ #pos
292
+ #tell
293
+ ```
294
+
295
+ See [`IO`](https://ruby-doc.org/core-2.6.1/IO.html) docs.
296
+
297
+ ```
298
+ #read(bytes_to_read = nil, out_buffer = nil)
299
+ #eof?
300
+ #rewind
301
+ #close
302
+ #closed?
303
+ ```
304
+
305
+ See [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.6.1/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
306
+
307
+ ```
308
+ #readpartial(bytes_to_read = nil, out_buffer = nil)
309
+ #read_nonblock(bytes_to_read, out_buffer = nil, *options)
310
+ ```
311
+
312
+ See [`IO`](https://ruby-doc.org/core-2.6.1/IO.html) docs.
313
+
314
+ ```
315
+ #getbyte
316
+ #each_byte(&block)
317
+ #readbyte
318
+ #ungetbyte(byte)
319
+
320
+ #getc
321
+ #readchar
322
+ #each_char(&block)
323
+ #ungetc(char)
324
+
325
+ #lineno
326
+ #lineno=
327
+ #gets(separator = $OUTPUT_RECORD_SEPARATOR, limit = nil)
328
+ #readline
329
+ #readlines
330
+ #each(&block)
331
+ #each_line(&block)
332
+ #ungetline(line)
333
+ ```
334
+
335
+ Typical helpers, see [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.6.1/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
336
+
337
+ ## License
338
+
339
+ MIT license, see LICENSE and AUTHORS.
@@ -0,0 +1,16 @@
1
+ // Ruby bindings for brotli library.
2
+ // Copyright (c) 2019 AUTHORS, MIT License.
3
+
4
+ #include "brs_ext/buffer.h"
5
+
6
+ #include "ruby.h"
7
+
8
+ void brs_ext_buffer_exports(VALUE root_module)
9
+ {
10
+ VALUE option = rb_define_module_under(root_module, "Buffer");
11
+
12
+ rb_define_const(option, "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR", UINT2NUM(BRS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR));
13
+ rb_define_const(option, "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR", UINT2NUM(BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR));
14
+ rb_define_const(option, "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR", UINT2NUM(BRS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR));
15
+ rb_define_const(option, "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR", UINT2NUM(BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR));
16
+ }
@@ -0,0 +1,17 @@
1
+ // Ruby bindings for brotli library.
2
+ // Copyright (c) 2019 AUTHORS, MIT License.
3
+
4
+ #if !defined(BRS_EXT_BUFFER_H)
5
+ #define BRS_EXT_BUFFER_H
6
+
7
+ #include "ruby.h"
8
+
9
+ #define BRS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR (1 << 18) // 256 KB
10
+ #define BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR (1 << 16) // 64 KB
11
+
12
+ #define BRS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR (1 << 16) // 64 KB
13
+ #define BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR (1 << 18) // 256 KB
14
+
15
+ void brs_ext_buffer_exports(VALUE root_module);
16
+
17
+ #endif // BRS_EXT_BUFFER_H
@@ -0,0 +1,13 @@
1
+ // Ruby bindings for brotli library.
2
+ // Copyright (c) 2019 AUTHORS, MIT License.
3
+
4
+ #if !defined(BRS_EXT_COMMON_H)
5
+ #define BRS_EXT_COMMON_H
6
+
7
+ #include <stdint.h>
8
+
9
+ #define BRS_EXT_MODULE_NAME "BRS"
10
+
11
+ typedef uint_fast8_t brs_ext_result_t;
12
+
13
+ #endif // BRS_EXT_COMMON_H
@@ -0,0 +1,78 @@
1
+ // Ruby bindings for brotli library.
2
+ // Copyright (c) 2019 AUTHORS, MIT License.
3
+
4
+ #include "brs_ext/error.h"
5
+
6
+ #include <brotli/decode.h>
7
+
8
+ #include "brs_ext/common.h"
9
+ #include "ruby.h"
10
+
11
+ brs_ext_result_t brs_ext_get_decompressor_error(BrotliDecoderErrorCode error_code)
12
+ {
13
+ switch (error_code) {
14
+ case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:
15
+ case BROTLI_DECODER_ERROR_FORMAT_RESERVED:
16
+ case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:
17
+ case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:
18
+ case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:
19
+ case BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:
20
+ case BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:
21
+ case BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:
22
+ case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:
23
+ case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:
24
+ case BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:
25
+ case BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:
26
+ case BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:
27
+ case BROTLI_DECODER_ERROR_FORMAT_PADDING_1:
28
+ case BROTLI_DECODER_ERROR_FORMAT_PADDING_2:
29
+ case BROTLI_DECODER_ERROR_FORMAT_DISTANCE:
30
+ return BRS_EXT_ERROR_DECOMPRESSOR_CORRUPTED_SOURCE;
31
+ case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:
32
+ case BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:
33
+ case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:
34
+ case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:
35
+ case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:
36
+ case BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:
37
+ return BRS_EXT_ERROR_ALLOCATE_FAILED;
38
+ default:
39
+ return BRS_EXT_ERROR_UNEXPECTED;
40
+ }
41
+ }
42
+
43
+ static inline NORETURN(void raise(const char* name, const char* description))
44
+ {
45
+ VALUE module = rb_define_module(BRS_EXT_MODULE_NAME);
46
+ VALUE error = rb_const_get(module, rb_intern(name));
47
+ rb_raise(error, "%s", description);
48
+ }
49
+
50
+ void brs_ext_raise_error(brs_ext_result_t result)
51
+ {
52
+ switch (result) {
53
+ case BRS_EXT_ERROR_ALLOCATE_FAILED:
54
+ raise("AllocateError", "allocate error");
55
+ case BRS_EXT_ERROR_VALIDATE_FAILED:
56
+ raise("ValidateError", "validate error");
57
+
58
+ case BRS_EXT_ERROR_USED_AFTER_CLOSE:
59
+ raise("UsedAfterCloseError", "used after closed");
60
+ case BRS_EXT_ERROR_NOT_ENOUGH_SOURCE_BUFFER:
61
+ raise("NotEnoughSourceBufferError", "not enough source buffer");
62
+ case BRS_EXT_ERROR_NOT_ENOUGH_DESTINATION_BUFFER:
63
+ raise("NotEnoughDestinationBufferError", "not enough destination buffer");
64
+ case BRS_EXT_ERROR_DECOMPRESSOR_CORRUPTED_SOURCE:
65
+ raise("DecompressorCorruptedSourceError", "decompressor received corrupted source");
66
+
67
+ case BRS_EXT_ERROR_ACCESS_IO:
68
+ raise("AccessIOError", "failed to access IO");
69
+ case BRS_EXT_ERROR_READ_IO:
70
+ raise("ReadIOError", "failed to read IO");
71
+ case BRS_EXT_ERROR_WRITE_IO:
72
+ raise("WriteIOError", "failed to write IO");
73
+
74
+ default:
75
+ // BRS_EXT_ERROR_UNEXPECTED
76
+ raise("UnexpectedError", "unexpected error");
77
+ }
78
+ }
@@ -0,0 +1,34 @@
1
+ // Ruby bindings for brotli library.
2
+ // Copyright (c) 2019 AUTHORS, MIT License.
3
+
4
+ #if !defined(BRS_EXT_ERROR_H)
5
+ #define BRS_EXT_ERROR_H
6
+
7
+ #include <brotli/decode.h>
8
+
9
+ #include "brs_ext/common.h"
10
+ #include "ruby.h"
11
+
12
+ // Results for errors listed in "lib/brs/error" used in c extension.
13
+
14
+ enum {
15
+ BRS_EXT_ERROR_ALLOCATE_FAILED = 1,
16
+ BRS_EXT_ERROR_VALIDATE_FAILED,
17
+
18
+ BRS_EXT_ERROR_USED_AFTER_CLOSE,
19
+ BRS_EXT_ERROR_NOT_ENOUGH_SOURCE_BUFFER,
20
+ BRS_EXT_ERROR_NOT_ENOUGH_DESTINATION_BUFFER,
21
+ BRS_EXT_ERROR_DECOMPRESSOR_CORRUPTED_SOURCE,
22
+
23
+ BRS_EXT_ERROR_ACCESS_IO,
24
+ BRS_EXT_ERROR_READ_IO,
25
+ BRS_EXT_ERROR_WRITE_IO,
26
+
27
+ BRS_EXT_ERROR_UNEXPECTED
28
+ };
29
+
30
+ brs_ext_result_t brs_ext_get_decompressor_error(BrotliDecoderErrorCode error_code);
31
+
32
+ NORETURN(void brs_ext_raise_error(brs_ext_result_t result));
33
+
34
+ #endif // BRS_EXT_ERROR_H