zstd-ruby 1.5.6.5 → 1.5.6.7
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/.gitignore +1 -0
- data/README.md +76 -0
- data/ext/zstdruby/common.h +37 -11
- data/ext/zstdruby/main.c +4 -0
- data/ext/zstdruby/zstdruby.c +99 -7
- data/lib/zstd-ruby/stream_writer.rb +1 -1
- data/lib/zstd-ruby/version.rb +1 -1
- data/lib/zstd-ruby.rb +2 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9acf1d7797f3431d0df130388295910e47c9bdaf36df29e1f116a55b993c130d
|
4
|
+
data.tar.gz: c58e20e6f0c2d270a21481b8ac2ba1c427d8cc6b1c2e52305e5b7540fcda41bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fad54c87b430ddbd437dd5e238b873c7572b2ed23e7b2a6409b817e1a823ab943bd49278c989abc1470a30c7fc8ad983fcf18a0b1dad84f8b99625fee2e6097
|
7
|
+
data.tar.gz: d8dd762266849d491ac971bd7eb764ea9bda42da6ef6fbd351bc91ab792e18009f1d52f8005734489776c049b4ef82bd25042020be8cb286c73f94af86b1a2c7
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -49,6 +49,22 @@ compressed_data = Zstd.compress(data, level: complession_level) # default compre
|
|
49
49
|
compressed_using_dict = Zstd.compress("", dict: File.read('dictionary_file'))
|
50
50
|
```
|
51
51
|
|
52
|
+
#### Compression with CDict
|
53
|
+
|
54
|
+
If you use the same dictionary repeatedly, you can speed up the setup by creating CDict in advance:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
cdict = Zstd::CDict.new(File.read('dictionary_file'))
|
58
|
+
compressed_using_dict = Zstd.compress("", dict: cdict)
|
59
|
+
```
|
60
|
+
|
61
|
+
The compression_level can be specified on creating CDict.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
cdict = Zstd::CDict.new(File.read('dictionary_file'), 5)
|
65
|
+
compressed_using_dict = Zstd.compress("", dict: cdict)
|
66
|
+
```
|
67
|
+
|
52
68
|
#### Streaming Compression
|
53
69
|
```ruby
|
54
70
|
stream = Zstd::StreamingCompress.new
|
@@ -86,6 +102,16 @@ stream << "ghi"
|
|
86
102
|
res << stream.finish
|
87
103
|
```
|
88
104
|
|
105
|
+
#### Streaming Compression with CDict of level 5
|
106
|
+
```ruby
|
107
|
+
cdict = Zstd::CDict.new(File.read('dictionary_file', 5)
|
108
|
+
stream = Zstd::StreamingCompress.new(dict: cdict)
|
109
|
+
stream << "abc" << "def"
|
110
|
+
res = stream.flush
|
111
|
+
stream << "ghi"
|
112
|
+
res << stream.finish
|
113
|
+
```
|
114
|
+
|
89
115
|
### Decompression
|
90
116
|
|
91
117
|
#### Simple Decompression
|
@@ -100,6 +126,15 @@ data = Zstd.decompress(compressed_data)
|
|
100
126
|
Zstd.decompress(compressed_using_dict, dict: File.read('dictionary_file'))
|
101
127
|
```
|
102
128
|
|
129
|
+
#### Decompression with DDict
|
130
|
+
|
131
|
+
If you use the same dictionary repeatedly, you can speed up the setup by creating DDict in advance:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
ddict = Zstd::Ddict.new(File.read('dictionary_file'))
|
135
|
+
data = Zstd.compress(compressed_using_dict, ddict)
|
136
|
+
```
|
137
|
+
|
103
138
|
#### Streaming Decompression
|
104
139
|
```ruby
|
105
140
|
cstr = "" # Compressed data
|
@@ -118,6 +153,8 @@ result << stream.decompress(cstr[0, 10])
|
|
118
153
|
result << stream.decompress(cstr[10..-1])
|
119
154
|
```
|
120
155
|
|
156
|
+
DDict can also be specified to `dict:`.
|
157
|
+
|
121
158
|
### Skippable frame
|
122
159
|
|
123
160
|
```ruby
|
@@ -127,6 +164,45 @@ Zstd.read_skippable_frame(compressed_data_with_skippable_frame)
|
|
127
164
|
# => "sample data"
|
128
165
|
```
|
129
166
|
|
167
|
+
### Stream Writer and Reader Wrapper
|
168
|
+
**EXPERIMENTAL**
|
169
|
+
|
170
|
+
* These features are experimental and may be subject to API changes in future releases.
|
171
|
+
* There may be performance and compatibility issues, so extensive testing is required before production use.
|
172
|
+
* If you have any questions, encounter bugs, or have suggestions, please report them via [GitHub issues](https://github.com/SpringMT/zstd-ruby/issues).
|
173
|
+
|
174
|
+
#### Zstd::StreamWriter
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
require 'stringio'
|
178
|
+
require 'zstd-ruby'
|
179
|
+
|
180
|
+
io = StringIO.new
|
181
|
+
stream = Zstd::StreamWriter.new(io)
|
182
|
+
stream.write("abc")
|
183
|
+
stream.finish
|
184
|
+
|
185
|
+
io.rewind
|
186
|
+
# Retrieve the compressed data
|
187
|
+
compressed_data = io.read
|
188
|
+
```
|
189
|
+
|
190
|
+
#### Zstd::StreamReader
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
require 'stringio'
|
194
|
+
require 'zstd-ruby' # Add the appropriate require statement if necessary
|
195
|
+
|
196
|
+
io = StringIO.new(compressed_data)
|
197
|
+
reader = Zstd::StreamReader.new(io)
|
198
|
+
|
199
|
+
# Read and output the decompressed data
|
200
|
+
puts reader.read(10) # 'abc'
|
201
|
+
puts reader.read(10) # 'def'
|
202
|
+
puts reader.read(10) # '' (end of data)
|
203
|
+
```
|
204
|
+
|
205
|
+
|
130
206
|
## JRuby
|
131
207
|
This gem does not support JRuby.
|
132
208
|
|
data/ext/zstdruby/common.h
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
#ifndef ZSTD_RUBY_H
|
2
2
|
#define ZSTD_RUBY_H 1
|
3
3
|
|
4
|
+
#include <stdbool.h>
|
4
5
|
#include <ruby.h>
|
5
6
|
#ifdef HAVE_RUBY_THREAD_H
|
6
7
|
#include <ruby/thread.h>
|
7
8
|
#endif
|
8
|
-
#include <stdbool.h>
|
9
9
|
#include "./libzstd/zstd.h"
|
10
10
|
|
11
|
+
extern VALUE rb_cCDict, rb_cDDict;
|
12
|
+
|
11
13
|
static int convert_compression_level(VALUE compression_level_value)
|
12
14
|
{
|
13
15
|
if (NIL_P(compression_level_value)) {
|
@@ -34,12 +36,24 @@ static void set_compress_params(ZSTD_CCtx* const ctx, VALUE level_from_args, VAL
|
|
34
36
|
ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, compression_level);
|
35
37
|
|
36
38
|
if (kwargs_values[1] != Qundef && kwargs_values[1] != Qnil) {
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
if (CLASS_OF(kwargs_values[1]) == rb_cCDict) {
|
40
|
+
ZSTD_CDict* cdict = DATA_PTR(kwargs_values[1]);
|
41
|
+
size_t ref_dict_ret = ZSTD_CCtx_refCDict(ctx, cdict);
|
42
|
+
if (ZSTD_isError(ref_dict_ret)) {
|
43
|
+
ZSTD_freeCCtx(ctx);
|
44
|
+
rb_raise(rb_eRuntimeError, "%s", "ZSTD_CCtx_refCDict failed");
|
45
|
+
}
|
46
|
+
} else if (TYPE(kwargs_values[1]) == T_STRING) {
|
47
|
+
char* dict_buffer = RSTRING_PTR(kwargs_values[1]);
|
48
|
+
size_t dict_size = RSTRING_LEN(kwargs_values[1]);
|
49
|
+
size_t load_dict_ret = ZSTD_CCtx_loadDictionary(ctx, dict_buffer, dict_size);
|
50
|
+
if (ZSTD_isError(load_dict_ret)) {
|
51
|
+
ZSTD_freeCCtx(ctx);
|
52
|
+
rb_raise(rb_eRuntimeError, "%s", "ZSTD_CCtx_loadDictionary failed");
|
53
|
+
}
|
54
|
+
} else {
|
41
55
|
ZSTD_freeCCtx(ctx);
|
42
|
-
rb_raise(
|
56
|
+
rb_raise(rb_eArgError, "`dict:` must be a Zstd::CDict or a String");
|
43
57
|
}
|
44
58
|
}
|
45
59
|
}
|
@@ -113,12 +127,24 @@ static void set_decompress_params(ZSTD_DCtx* const dctx, VALUE kwargs)
|
|
113
127
|
rb_get_kwargs(kwargs, kwargs_keys, 0, 1, kwargs_values);
|
114
128
|
|
115
129
|
if (kwargs_values[0] != Qundef && kwargs_values[0] != Qnil) {
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
130
|
+
if (CLASS_OF(kwargs_values[0]) == rb_cDDict) {
|
131
|
+
ZSTD_DDict* ddict = DATA_PTR(kwargs_values[0]);
|
132
|
+
size_t ref_dict_ret = ZSTD_DCtx_refDDict(dctx, ddict);
|
133
|
+
if (ZSTD_isError(ref_dict_ret)) {
|
134
|
+
ZSTD_freeDCtx(dctx);
|
135
|
+
rb_raise(rb_eRuntimeError, "%s", "ZSTD_DCtx_refDDict failed");
|
136
|
+
}
|
137
|
+
} else if (TYPE(kwargs_values[0]) == T_STRING) {
|
138
|
+
char* dict_buffer = RSTRING_PTR(kwargs_values[0]);
|
139
|
+
size_t dict_size = RSTRING_LEN(kwargs_values[0]);
|
140
|
+
size_t load_dict_ret = ZSTD_DCtx_loadDictionary(dctx, dict_buffer, dict_size);
|
141
|
+
if (ZSTD_isError(load_dict_ret)) {
|
142
|
+
ZSTD_freeDCtx(dctx);
|
143
|
+
rb_raise(rb_eRuntimeError, "%s", "ZSTD_CCtx_loadDictionary failed");
|
144
|
+
}
|
145
|
+
} else {
|
120
146
|
ZSTD_freeDCtx(dctx);
|
121
|
-
rb_raise(
|
147
|
+
rb_raise(rb_eArgError, "`dict:` must be a Zstd::DDict or a String");
|
122
148
|
}
|
123
149
|
}
|
124
150
|
}
|
data/ext/zstdruby/main.c
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
#include "common.h"
|
2
2
|
|
3
3
|
VALUE rb_mZstd;
|
4
|
+
VALUE rb_cCDict;
|
5
|
+
VALUE rb_cDDict;
|
4
6
|
void zstd_ruby_init(void);
|
5
7
|
void zstd_ruby_skippable_frame_init(void);
|
6
8
|
void zstd_ruby_streaming_compress_init(void);
|
@@ -14,6 +16,8 @@ Init_zstdruby(void)
|
|
14
16
|
#endif
|
15
17
|
|
16
18
|
rb_mZstd = rb_define_module("Zstd");
|
19
|
+
rb_cCDict = rb_define_class_under(rb_mZstd, "CDict", rb_cObject);
|
20
|
+
rb_cDDict = rb_define_class_under(rb_mZstd, "DDict", rb_cObject);
|
17
21
|
zstd_ruby_init();
|
18
22
|
zstd_ruby_skippable_frame_init();
|
19
23
|
zstd_ruby_streaming_compress_init();
|
data/ext/zstdruby/zstdruby.c
CHANGED
@@ -87,13 +87,13 @@ static VALUE rb_compress_using_dict(int argc, VALUE *argv, VALUE self)
|
|
87
87
|
|
88
88
|
static VALUE decompress_buffered(ZSTD_DCtx* dctx, const char* input_data, size_t input_size)
|
89
89
|
{
|
90
|
-
VALUE output_string = rb_str_new(NULL, 0);
|
91
|
-
ZSTD_outBuffer output = { NULL, 0, 0 };
|
92
|
-
|
93
90
|
ZSTD_inBuffer input = { input_data, input_size, 0 };
|
91
|
+
VALUE result = rb_str_new(0, 0);
|
92
|
+
|
94
93
|
while (input.pos < input.size) {
|
94
|
+
ZSTD_outBuffer output = { NULL, 0, 0 };
|
95
95
|
output.size += ZSTD_DStreamOutSize();
|
96
|
-
|
96
|
+
VALUE output_string = rb_str_new(NULL, output.size);
|
97
97
|
output.dst = RSTRING_PTR(output_string);
|
98
98
|
|
99
99
|
size_t ret = zstd_stream_decompress(dctx, &output, &input, false);
|
@@ -101,10 +101,10 @@ static VALUE decompress_buffered(ZSTD_DCtx* dctx, const char* input_data, size_t
|
|
101
101
|
ZSTD_freeDCtx(dctx);
|
102
102
|
rb_raise(rb_eRuntimeError, "%s: %s", "ZSTD_decompressStream failed", ZSTD_getErrorName(ret));
|
103
103
|
}
|
104
|
+
rb_str_cat(result, output.dst, output.pos);
|
104
105
|
}
|
105
|
-
rb_str_resize(output_string, output.pos);
|
106
106
|
ZSTD_freeDCtx(dctx);
|
107
|
-
return
|
107
|
+
return result;
|
108
108
|
}
|
109
109
|
|
110
110
|
static VALUE rb_decompress(int argc, VALUE *argv, VALUE self)
|
@@ -134,7 +134,7 @@ static VALUE rb_decompress(int argc, VALUE *argv, VALUE self)
|
|
134
134
|
VALUE output = rb_str_new(NULL, uncompressed_size);
|
135
135
|
char* output_data = RSTRING_PTR(output);
|
136
136
|
|
137
|
-
size_t const decompress_size =
|
137
|
+
size_t const decompress_size = zstd_decompress(dctx, output_data, uncompressed_size, input_data, input_size, false);
|
138
138
|
if (ZSTD_isError(decompress_size)) {
|
139
139
|
rb_raise(rb_eRuntimeError, "%s: %s", "decompress error", ZSTD_getErrorName(decompress_size));
|
140
140
|
}
|
@@ -195,6 +195,90 @@ static VALUE rb_decompress_using_dict(int argc, VALUE *argv, VALUE self)
|
|
195
195
|
return output;
|
196
196
|
}
|
197
197
|
|
198
|
+
static void free_cdict(void *dict)
|
199
|
+
{
|
200
|
+
ZSTD_freeCDict(dict);
|
201
|
+
}
|
202
|
+
|
203
|
+
static size_t sizeof_cdict(const void *dict)
|
204
|
+
{
|
205
|
+
return ZSTD_sizeof_CDict(dict);
|
206
|
+
}
|
207
|
+
|
208
|
+
static void free_ddict(void *dict)
|
209
|
+
{
|
210
|
+
ZSTD_freeDDict(dict);
|
211
|
+
}
|
212
|
+
|
213
|
+
static size_t sizeof_ddict(const void *dict)
|
214
|
+
{
|
215
|
+
return ZSTD_sizeof_DDict(dict);
|
216
|
+
}
|
217
|
+
|
218
|
+
static const rb_data_type_t cdict_type = {
|
219
|
+
"Zstd::CDict",
|
220
|
+
{0, free_cdict, sizeof_cdict,},
|
221
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
222
|
+
};
|
223
|
+
|
224
|
+
static const rb_data_type_t ddict_type = {
|
225
|
+
"Zstd::DDict",
|
226
|
+
{0, free_ddict, sizeof_ddict,},
|
227
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
228
|
+
};
|
229
|
+
|
230
|
+
static VALUE rb_cdict_alloc(VALUE self)
|
231
|
+
{
|
232
|
+
ZSTD_CDict* cdict = NULL;
|
233
|
+
return TypedData_Wrap_Struct(self, &cdict_type, cdict);
|
234
|
+
}
|
235
|
+
|
236
|
+
static VALUE rb_cdict_initialize(int argc, VALUE *argv, VALUE self)
|
237
|
+
{
|
238
|
+
VALUE dict;
|
239
|
+
VALUE compression_level_value;
|
240
|
+
rb_scan_args(argc, argv, "11", &dict, &compression_level_value);
|
241
|
+
int compression_level = convert_compression_level(compression_level_value);
|
242
|
+
|
243
|
+
StringValue(dict);
|
244
|
+
char* dict_buffer = RSTRING_PTR(dict);
|
245
|
+
size_t dict_size = RSTRING_LEN(dict);
|
246
|
+
|
247
|
+
ZSTD_CDict* const cdict = ZSTD_createCDict(dict_buffer, dict_size, compression_level);
|
248
|
+
if (cdict == NULL) {
|
249
|
+
rb_raise(rb_eRuntimeError, "%s", "ZSTD_createCDict failed");
|
250
|
+
}
|
251
|
+
|
252
|
+
DATA_PTR(self) = cdict;
|
253
|
+
return self;
|
254
|
+
}
|
255
|
+
|
256
|
+
static VALUE rb_ddict_alloc(VALUE self)
|
257
|
+
{
|
258
|
+
ZSTD_CDict* ddict = NULL;
|
259
|
+
return TypedData_Wrap_Struct(self, &ddict_type, ddict);
|
260
|
+
}
|
261
|
+
|
262
|
+
static VALUE rb_ddict_initialize(VALUE self, VALUE dict)
|
263
|
+
{
|
264
|
+
StringValue(dict);
|
265
|
+
char* dict_buffer = RSTRING_PTR(dict);
|
266
|
+
size_t dict_size = RSTRING_LEN(dict);
|
267
|
+
|
268
|
+
ZSTD_DDict* const ddict = ZSTD_createDDict(dict_buffer, dict_size);
|
269
|
+
if (ddict == NULL) {
|
270
|
+
rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDDict failed");
|
271
|
+
}
|
272
|
+
|
273
|
+
DATA_PTR(self) = ddict;
|
274
|
+
return self;
|
275
|
+
}
|
276
|
+
|
277
|
+
static VALUE rb_prohibit_copy(VALUE self, VALUE obj)
|
278
|
+
{
|
279
|
+
rb_raise(rb_eRuntimeError, "CDict cannot be duplicated");
|
280
|
+
}
|
281
|
+
|
198
282
|
void
|
199
283
|
zstd_ruby_init(void)
|
200
284
|
{
|
@@ -203,4 +287,12 @@ zstd_ruby_init(void)
|
|
203
287
|
rb_define_module_function(rb_mZstd, "compress_using_dict", rb_compress_using_dict, -1);
|
204
288
|
rb_define_module_function(rb_mZstd, "decompress", rb_decompress, -1);
|
205
289
|
rb_define_module_function(rb_mZstd, "decompress_using_dict", rb_decompress_using_dict, -1);
|
290
|
+
|
291
|
+
rb_define_alloc_func(rb_cCDict, rb_cdict_alloc);
|
292
|
+
rb_define_private_method(rb_cCDict, "initialize", rb_cdict_initialize, -1);
|
293
|
+
rb_define_method(rb_cCDict, "initialize_copy", rb_prohibit_copy, 1);
|
294
|
+
|
295
|
+
rb_define_alloc_func(rb_cDDict, rb_ddict_alloc);
|
296
|
+
rb_define_private_method(rb_cDDict, "initialize", rb_ddict_initialize, 1);
|
297
|
+
rb_define_method(rb_cDDict, "initialize_copy", rb_prohibit_copy, 1);
|
206
298
|
}
|
data/lib/zstd-ruby/version.rb
CHANGED
data/lib/zstd-ruby.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zstd-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.6.
|
4
|
+
version: 1.5.6.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SpringMT
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -200,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
200
200
|
- !ruby/object:Gem::Version
|
201
201
|
version: '0'
|
202
202
|
requirements: []
|
203
|
-
rubygems_version: 3.
|
203
|
+
rubygems_version: 3.4.19
|
204
204
|
signing_key:
|
205
205
|
specification_version: 4
|
206
206
|
summary: Ruby binding for zstd(Zstandard - Fast real-time compression algorithm)
|