vibe_zstd 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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.standard.yml +3 -0
  3. data/CHANGELOG.md +22 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +978 -0
  6. data/Rakefile +20 -0
  7. data/benchmark/README.md +198 -0
  8. data/benchmark/compression_levels.rb +99 -0
  9. data/benchmark/context_reuse.rb +174 -0
  10. data/benchmark/decompression_speed_by_level.rb +65 -0
  11. data/benchmark/dictionary_training.rb +182 -0
  12. data/benchmark/dictionary_usage.rb +121 -0
  13. data/benchmark/for_readme.rb +157 -0
  14. data/benchmark/generate_fixture.rb +82 -0
  15. data/benchmark/helpers.rb +237 -0
  16. data/benchmark/multithreading.rb +105 -0
  17. data/benchmark/run_all.rb +150 -0
  18. data/benchmark/streaming.rb +154 -0
  19. data/ext/vibe_zstd/Makefile +270 -0
  20. data/ext/vibe_zstd/cctx.c +565 -0
  21. data/ext/vibe_zstd/dctx.c +493 -0
  22. data/ext/vibe_zstd/dict.c +587 -0
  23. data/ext/vibe_zstd/extconf.rb +52 -0
  24. data/ext/vibe_zstd/frames.c +132 -0
  25. data/ext/vibe_zstd/libzstd/LICENSE +30 -0
  26. data/ext/vibe_zstd/libzstd/common/allocations.h +55 -0
  27. data/ext/vibe_zstd/libzstd/common/bits.h +205 -0
  28. data/ext/vibe_zstd/libzstd/common/bitstream.h +454 -0
  29. data/ext/vibe_zstd/libzstd/common/compiler.h +464 -0
  30. data/ext/vibe_zstd/libzstd/common/cpu.h +249 -0
  31. data/ext/vibe_zstd/libzstd/common/debug.c +30 -0
  32. data/ext/vibe_zstd/libzstd/common/debug.h +107 -0
  33. data/ext/vibe_zstd/libzstd/common/entropy_common.c +340 -0
  34. data/ext/vibe_zstd/libzstd/common/error_private.c +64 -0
  35. data/ext/vibe_zstd/libzstd/common/error_private.h +158 -0
  36. data/ext/vibe_zstd/libzstd/common/fse.h +625 -0
  37. data/ext/vibe_zstd/libzstd/common/fse_decompress.c +315 -0
  38. data/ext/vibe_zstd/libzstd/common/huf.h +277 -0
  39. data/ext/vibe_zstd/libzstd/common/mem.h +422 -0
  40. data/ext/vibe_zstd/libzstd/common/pool.c +371 -0
  41. data/ext/vibe_zstd/libzstd/common/pool.h +81 -0
  42. data/ext/vibe_zstd/libzstd/common/portability_macros.h +171 -0
  43. data/ext/vibe_zstd/libzstd/common/threading.c +182 -0
  44. data/ext/vibe_zstd/libzstd/common/threading.h +142 -0
  45. data/ext/vibe_zstd/libzstd/common/xxhash.c +18 -0
  46. data/ext/vibe_zstd/libzstd/common/xxhash.h +7094 -0
  47. data/ext/vibe_zstd/libzstd/common/zstd_common.c +48 -0
  48. data/ext/vibe_zstd/libzstd/common/zstd_deps.h +123 -0
  49. data/ext/vibe_zstd/libzstd/common/zstd_internal.h +324 -0
  50. data/ext/vibe_zstd/libzstd/common/zstd_trace.h +156 -0
  51. data/ext/vibe_zstd/libzstd/compress/clevels.h +134 -0
  52. data/ext/vibe_zstd/libzstd/compress/fse_compress.c +625 -0
  53. data/ext/vibe_zstd/libzstd/compress/hist.c +191 -0
  54. data/ext/vibe_zstd/libzstd/compress/hist.h +82 -0
  55. data/ext/vibe_zstd/libzstd/compress/huf_compress.c +1464 -0
  56. data/ext/vibe_zstd/libzstd/compress/zstd_compress.c +7843 -0
  57. data/ext/vibe_zstd/libzstd/compress/zstd_compress_internal.h +1636 -0
  58. data/ext/vibe_zstd/libzstd/compress/zstd_compress_literals.c +235 -0
  59. data/ext/vibe_zstd/libzstd/compress/zstd_compress_literals.h +39 -0
  60. data/ext/vibe_zstd/libzstd/compress/zstd_compress_sequences.c +442 -0
  61. data/ext/vibe_zstd/libzstd/compress/zstd_compress_sequences.h +55 -0
  62. data/ext/vibe_zstd/libzstd/compress/zstd_compress_superblock.c +688 -0
  63. data/ext/vibe_zstd/libzstd/compress/zstd_compress_superblock.h +32 -0
  64. data/ext/vibe_zstd/libzstd/compress/zstd_cwksp.h +765 -0
  65. data/ext/vibe_zstd/libzstd/compress/zstd_double_fast.c +778 -0
  66. data/ext/vibe_zstd/libzstd/compress/zstd_double_fast.h +42 -0
  67. data/ext/vibe_zstd/libzstd/compress/zstd_fast.c +985 -0
  68. data/ext/vibe_zstd/libzstd/compress/zstd_fast.h +30 -0
  69. data/ext/vibe_zstd/libzstd/compress/zstd_lazy.c +2199 -0
  70. data/ext/vibe_zstd/libzstd/compress/zstd_lazy.h +193 -0
  71. data/ext/vibe_zstd/libzstd/compress/zstd_ldm.c +745 -0
  72. data/ext/vibe_zstd/libzstd/compress/zstd_ldm.h +109 -0
  73. data/ext/vibe_zstd/libzstd/compress/zstd_ldm_geartab.h +106 -0
  74. data/ext/vibe_zstd/libzstd/compress/zstd_opt.c +1580 -0
  75. data/ext/vibe_zstd/libzstd/compress/zstd_opt.h +72 -0
  76. data/ext/vibe_zstd/libzstd/compress/zstd_preSplit.c +238 -0
  77. data/ext/vibe_zstd/libzstd/compress/zstd_preSplit.h +33 -0
  78. data/ext/vibe_zstd/libzstd/compress/zstdmt_compress.c +1923 -0
  79. data/ext/vibe_zstd/libzstd/compress/zstdmt_compress.h +102 -0
  80. data/ext/vibe_zstd/libzstd/decompress/huf_decompress.c +1944 -0
  81. data/ext/vibe_zstd/libzstd/decompress/huf_decompress_amd64.S +602 -0
  82. data/ext/vibe_zstd/libzstd/decompress/zstd_ddict.c +244 -0
  83. data/ext/vibe_zstd/libzstd/decompress/zstd_ddict.h +44 -0
  84. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress.c +2410 -0
  85. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress_block.c +2209 -0
  86. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress_block.h +73 -0
  87. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress_internal.h +240 -0
  88. data/ext/vibe_zstd/libzstd/deprecated/zbuff.h +214 -0
  89. data/ext/vibe_zstd/libzstd/deprecated/zbuff_common.c +26 -0
  90. data/ext/vibe_zstd/libzstd/deprecated/zbuff_compress.c +167 -0
  91. data/ext/vibe_zstd/libzstd/deprecated/zbuff_decompress.c +77 -0
  92. data/ext/vibe_zstd/libzstd/dictBuilder/cover.c +1302 -0
  93. data/ext/vibe_zstd/libzstd/dictBuilder/cover.h +152 -0
  94. data/ext/vibe_zstd/libzstd/dictBuilder/divsufsort.c +1913 -0
  95. data/ext/vibe_zstd/libzstd/dictBuilder/divsufsort.h +57 -0
  96. data/ext/vibe_zstd/libzstd/dictBuilder/fastcover.c +766 -0
  97. data/ext/vibe_zstd/libzstd/dictBuilder/zdict.c +1133 -0
  98. data/ext/vibe_zstd/libzstd/zdict.h +481 -0
  99. data/ext/vibe_zstd/libzstd/zstd.h +3198 -0
  100. data/ext/vibe_zstd/libzstd/zstd_errors.h +107 -0
  101. data/ext/vibe_zstd/streaming.c +410 -0
  102. data/ext/vibe_zstd/vibe_zstd.c +293 -0
  103. data/ext/vibe_zstd/vibe_zstd.h +56 -0
  104. data/ext/vibe_zstd/vibe_zstd_internal.h +27 -0
  105. data/lib/vibe_zstd/constants.rb +67 -0
  106. data/lib/vibe_zstd/version.rb +5 -0
  107. data/lib/vibe_zstd.rb +255 -0
  108. data/sig/vibe_zstd.rbs +76 -0
  109. metadata +179 -0
@@ -0,0 +1,565 @@
1
+ // CCtx implementation for VibeZstd
2
+ #include "vibe_zstd_internal.h"
3
+
4
+ // TypedData type - defined in vibe_zstd.c
5
+ extern rb_data_type_t vibe_zstd_cctx_type;
6
+
7
+ // Helper to set CCtx parameter from Ruby keyword argument
8
+ static int
9
+ vibe_zstd_cctx_init_param_iter(VALUE key, VALUE value, VALUE self) {
10
+ // Build the setter method name: key + "="
11
+ const char* key_str = rb_id2name(SYM2ID(key));
12
+ size_t setter_len = strlen(key_str) + 2; // +1 for '=' + 1 for '\0'
13
+ char* setter = ALLOC_N(char, setter_len);
14
+ snprintf(setter, setter_len, "%s=", key_str);
15
+
16
+ // Call the setter method
17
+ rb_funcall(self, rb_intern(setter), 1, value);
18
+
19
+ xfree(setter);
20
+ return ST_CONTINUE;
21
+ }
22
+
23
+ static VALUE
24
+ vibe_zstd_cctx_initialize(int argc, VALUE* argv, VALUE self) {
25
+ VALUE options;
26
+ rb_scan_args(argc, argv, "0:", &options);
27
+
28
+ // If keyword arguments provided, set parameters
29
+ if (!NIL_P(options)) {
30
+ rb_hash_foreach(options, vibe_zstd_cctx_init_param_iter, self);
31
+ }
32
+
33
+ return self;
34
+ }
35
+
36
+ // CCtx.estimate_memory(level)
37
+ static VALUE
38
+ vibe_zstd_cctx_estimate_memory(VALUE self, VALUE level) {
39
+ int lvl = NUM2INT(level);
40
+ size_t estimate = ZSTD_estimateCCtxSize(lvl);
41
+ return SIZET2NUM(estimate);
42
+ }
43
+
44
+ // Compress args for GVL release
45
+ // This structure packages all arguments needed for compression so we can
46
+ // call ZSTD functions without holding Ruby's Global VM Lock (GVL).
47
+ // Releasing the GVL allows other Ruby threads to run during CPU-intensive compression.
48
+ typedef struct {
49
+ ZSTD_CCtx* cctx;
50
+ ZSTD_CDict* cdict;
51
+ const void* src;
52
+ size_t srcSize;
53
+ void* dst;
54
+ size_t dstCapacity;
55
+ int compressionLevel;
56
+ size_t result;
57
+ } compress_args;
58
+
59
+ // Compress without holding Ruby's GVL
60
+ // Called via rb_thread_call_without_gvl to allow parallel Ruby thread execution
61
+ // during CPU-intensive compression operations
62
+ static void*
63
+ compress_without_gvl(void* arg) {
64
+ compress_args* args = arg;
65
+ if (args->cdict) {
66
+ args->result = ZSTD_compress_usingCDict(args->cctx, args->dst, args->dstCapacity, args->src, args->srcSize, args->cdict);
67
+ } else {
68
+ args->result = ZSTD_compressCCtx(args->cctx, args->dst, args->dstCapacity, args->src, args->srcSize, args->compressionLevel);
69
+ }
70
+ return NULL;
71
+ }
72
+
73
+ // CCtx compress - Compress data using this context
74
+ //
75
+ // Supports per-operation parameters via keyword arguments:
76
+ // - level: Compression level (overrides context setting for this operation)
77
+ // - dict: CDict to use for compression
78
+ // - pledged_size: Expected input size for optimization (optional)
79
+ //
80
+ // Uses ZSTD_compressBound to allocate worst-case output buffer size,
81
+ // which is the recommended approach for one-shot compression.
82
+ // Releases GVL during compression to allow other Ruby threads to run.
83
+ static VALUE
84
+ vibe_zstd_cctx_compress(int argc, VALUE* argv, VALUE self) {
85
+ VALUE data, options = Qnil;
86
+ rb_scan_args(argc, argv, "1:", &data, &options);
87
+ vibe_zstd_cctx* cctx;
88
+ TypedData_Get_Struct(self, vibe_zstd_cctx, &vibe_zstd_cctx_type, cctx);
89
+ StringValue(data);
90
+
91
+ // Extract keyword arguments
92
+ int lvl = ZSTD_defaultCLevel();
93
+ ZSTD_CDict* cdict = NULL;
94
+ unsigned long long pledged_size = ZSTD_CONTENTSIZE_UNKNOWN;
95
+
96
+ if (!NIL_P(options)) {
97
+ // Handle level keyword argument
98
+ VALUE level_val = rb_hash_aref(options, ID2SYM(rb_intern("level")));
99
+ if (!NIL_P(level_val)) {
100
+ lvl = NUM2INT(level_val);
101
+ }
102
+
103
+ // Handle dict keyword argument
104
+ VALUE dict_val = rb_hash_aref(options, ID2SYM(rb_intern("dict")));
105
+ if (!NIL_P(dict_val)) {
106
+ vibe_zstd_cdict* cdict_struct;
107
+ TypedData_Get_Struct(dict_val, vibe_zstd_cdict, &vibe_zstd_cdict_type, cdict_struct);
108
+ cdict = cdict_struct->cdict;
109
+ }
110
+
111
+ // Handle pledged_size keyword argument
112
+ VALUE pledged_size_val = rb_hash_aref(options, ID2SYM(rb_intern("pledged_size")));
113
+ if (!NIL_P(pledged_size_val)) {
114
+ pledged_size = NUM2ULL(pledged_size_val);
115
+ }
116
+ }
117
+
118
+ // Set pledged size if provided
119
+ if (pledged_size != ZSTD_CONTENTSIZE_UNKNOWN) {
120
+ size_t result = ZSTD_CCtx_setPledgedSrcSize(cctx->cctx, pledged_size);
121
+ if (ZSTD_isError(result)) {
122
+ rb_raise(rb_eRuntimeError, "Failed to set pledged_size %llu: %s", pledged_size, ZSTD_getErrorName(result));
123
+ }
124
+ }
125
+
126
+ size_t srcSize = RSTRING_LEN(data);
127
+ size_t dstCapacity = ZSTD_compressBound(srcSize);
128
+ VALUE result_str = rb_str_new(NULL, dstCapacity);
129
+ compress_args args = {
130
+ .cctx = cctx->cctx,
131
+ .cdict = cdict,
132
+ .src = RSTRING_PTR(data),
133
+ .srcSize = srcSize,
134
+ .dst = RSTRING_PTR(result_str),
135
+ .dstCapacity = dstCapacity,
136
+ .compressionLevel = lvl,
137
+ .result = 0
138
+ };
139
+ rb_thread_call_without_gvl(compress_without_gvl, &args, NULL, NULL);
140
+ if (ZSTD_isError(args.result)) {
141
+ rb_raise(rb_eRuntimeError, "Compression failed: %s", ZSTD_getErrorName(args.result));
142
+ }
143
+ rb_str_set_len(result_str, args.result);
144
+ return result_str;
145
+ }
146
+
147
+ // Parameter lookup table for CCtx
148
+ typedef struct {
149
+ ID symbol_id;
150
+ ZSTD_cParameter param;
151
+ const char* name;
152
+ } cctx_param_entry;
153
+
154
+ static cctx_param_entry cctx_param_table[] = {
155
+ {0, ZSTD_c_compressionLevel, "compression_level"},
156
+ {0, ZSTD_c_windowLog, "window_log"},
157
+ {0, ZSTD_c_hashLog, "hash_log"},
158
+ {0, ZSTD_c_chainLog, "chain_log"},
159
+ {0, ZSTD_c_searchLog, "search_log"},
160
+ {0, ZSTD_c_minMatch, "min_match"},
161
+ {0, ZSTD_c_targetLength, "target_length"},
162
+ {0, ZSTD_c_strategy, "strategy"},
163
+ {0, ZSTD_c_targetCBlockSize, "target_cblock_size"},
164
+ {0, ZSTD_c_enableLongDistanceMatching, "enable_long_distance_matching"},
165
+ {0, ZSTD_c_ldmHashLog, "ldm_hash_log"},
166
+ {0, ZSTD_c_ldmMinMatch, "ldm_min_match"},
167
+ {0, ZSTD_c_ldmBucketSizeLog, "ldm_bucket_size_log"},
168
+ {0, ZSTD_c_ldmHashRateLog, "ldm_hash_rate_log"},
169
+ {0, ZSTD_c_contentSizeFlag, "content_size_flag"},
170
+ {0, ZSTD_c_checksumFlag, "checksum_flag"},
171
+ {0, ZSTD_c_dictIDFlag, "dict_id_flag"},
172
+ {0, ZSTD_c_nbWorkers, "workers"},
173
+ {0, ZSTD_c_jobSize, "job_size"},
174
+ {0, ZSTD_c_overlapLog, "overlap_log"},
175
+ {0, ZSTD_c_rsyncable, "rsyncable"},
176
+ {0, ZSTD_c_format, "format"},
177
+ {0, ZSTD_c_forceMaxWindow, "force_max_window"},
178
+ {0, ZSTD_c_forceAttachDict, "force_attach_dict"},
179
+ {0, ZSTD_c_literalCompressionMode, "literal_compression_mode"},
180
+ {0, ZSTD_c_srcSizeHint, "src_size_hint"},
181
+ {0, ZSTD_c_enableDedicatedDictSearch, "enable_dedicated_dict_search"},
182
+ {0, ZSTD_c_stableInBuffer, "stable_in_buffer"},
183
+ {0, ZSTD_c_stableOutBuffer, "stable_out_buffer"},
184
+ {0, ZSTD_c_blockDelimiters, "block_delimiters"},
185
+ {0, ZSTD_c_validateSequences, "validate_sequences"},
186
+ {0, ZSTD_c_useRowMatchFinder, "use_row_match_finder"},
187
+ {0, ZSTD_c_deterministicRefPrefix, "deterministic_ref_prefix"},
188
+ {0, ZSTD_c_prefetchCDictTables, "prefetch_cdict_tables"},
189
+ {0, ZSTD_c_enableSeqProducerFallback, "enable_seq_producer_fallback"},
190
+ {0, ZSTD_c_maxBlockSize, "max_block_size"},
191
+ {0, ZSTD_c_searchForExternalRepcodes, "search_for_external_repcodes"}
192
+ };
193
+
194
+ #define CCTX_PARAM_TABLE_SIZE (sizeof(cctx_param_table) / sizeof(cctx_param_entry))
195
+
196
+ // Initialize parameter lookup table symbol IDs
197
+ static void
198
+ init_cctx_param_table(void) {
199
+ for (size_t i = 0; i < CCTX_PARAM_TABLE_SIZE; i++) {
200
+ cctx_param_table[i].symbol_id = rb_intern(cctx_param_table[i].name);
201
+ }
202
+ }
203
+
204
+ // Helper: look up parameter enum from symbol ID
205
+ // Maps Ruby symbol (e.g., :compression_level) to ZSTD parameter constant
206
+ // Returns 1 if found, 0 if unknown parameter
207
+ static int
208
+ lookup_cctx_param(ID symbol_id, ZSTD_cParameter* param_out, const char** name_out) {
209
+ for (size_t i = 0; i < CCTX_PARAM_TABLE_SIZE; i++) {
210
+ if (cctx_param_table[i].symbol_id == symbol_id) {
211
+ *param_out = cctx_param_table[i].param;
212
+ if (name_out) *name_out = cctx_param_table[i].name;
213
+ return 1;
214
+ }
215
+ }
216
+ return 0;
217
+ }
218
+
219
+ // Generic setter with bounds checking
220
+ static VALUE
221
+ vibe_zstd_cctx_set_param_generic(VALUE self, VALUE value, ZSTD_cParameter param, const char* param_name) {
222
+ vibe_zstd_cctx* cctx;
223
+ TypedData_Get_Struct(self, vibe_zstd_cctx, &vibe_zstd_cctx_type, cctx);
224
+
225
+ int val = NUM2INT(value);
226
+
227
+ // Get bounds for validation
228
+ ZSTD_bounds bounds = ZSTD_cParam_getBounds(param);
229
+ if (ZSTD_isError(bounds.error)) {
230
+ rb_raise(rb_eRuntimeError, "Failed to get bounds for %s: %s",
231
+ param_name, ZSTD_getErrorName(bounds.error));
232
+ }
233
+
234
+ // Validate value is within bounds
235
+ if (val < bounds.lowerBound || val > bounds.upperBound) {
236
+ rb_raise(rb_eArgError, "%s must be between %d and %d (got %d)",
237
+ param_name, bounds.lowerBound, bounds.upperBound, val);
238
+ }
239
+
240
+ size_t result = ZSTD_CCtx_setParameter(cctx->cctx, param, val);
241
+ if (ZSTD_isError(result)) {
242
+ rb_raise(rb_eRuntimeError, "Failed to set %s: %s",
243
+ param_name, ZSTD_getErrorName(result));
244
+ }
245
+
246
+ return self;
247
+ }
248
+
249
+ // Boolean setter with Ruby true/false support
250
+ static VALUE
251
+ vibe_zstd_cctx_set_param_bool(VALUE self, VALUE value, ZSTD_cParameter param, const char* param_name) {
252
+ vibe_zstd_cctx* cctx;
253
+ TypedData_Get_Struct(self, vibe_zstd_cctx, &vibe_zstd_cctx_type, cctx);
254
+
255
+ // Convert Ruby boolean or integer to 0/1
256
+ // Handle integers explicitly: 0 -> false, non-zero -> true
257
+ // Handle booleans: false/nil -> false, everything else -> true
258
+ int val;
259
+ if (FIXNUM_P(value)) {
260
+ val = NUM2INT(value) != 0 ? 1 : 0;
261
+ } else {
262
+ val = RTEST(value) ? 1 : 0;
263
+ }
264
+
265
+ // Get bounds for validation
266
+ ZSTD_bounds bounds = ZSTD_cParam_getBounds(param);
267
+ if (ZSTD_isError(bounds.error)) {
268
+ rb_raise(rb_eRuntimeError, "Failed to get bounds for %s: %s",
269
+ param_name, ZSTD_getErrorName(bounds.error));
270
+ }
271
+
272
+ // Validate value is within bounds
273
+ if (val < bounds.lowerBound || val > bounds.upperBound) {
274
+ rb_raise(rb_eArgError, "%s must be between %d and %d (got %d)",
275
+ param_name, bounds.lowerBound, bounds.upperBound, val);
276
+ }
277
+
278
+ size_t result = ZSTD_CCtx_setParameter(cctx->cctx, param, val);
279
+ if (ZSTD_isError(result)) {
280
+ rb_raise(rb_eRuntimeError, "Failed to set %s: %s",
281
+ param_name, ZSTD_getErrorName(result));
282
+ }
283
+
284
+ return self;
285
+ }
286
+
287
+ // Generic getter
288
+ static VALUE
289
+ vibe_zstd_cctx_get_param_generic(VALUE self, ZSTD_cParameter param, const char* param_name) {
290
+ vibe_zstd_cctx* cctx;
291
+ TypedData_Get_Struct(self, vibe_zstd_cctx, &vibe_zstd_cctx_type, cctx);
292
+
293
+ int value;
294
+ size_t result = ZSTD_CCtx_getParameter(cctx->cctx, param, &value);
295
+ if (ZSTD_isError(result)) {
296
+ rb_raise(rb_eRuntimeError, "Failed to get %s: %s",
297
+ param_name, ZSTD_getErrorName(result));
298
+ }
299
+
300
+ return INT2NUM(value);
301
+ }
302
+
303
+ // Boolean getter returning Ruby true/false
304
+ static VALUE
305
+ vibe_zstd_cctx_get_param_bool(VALUE self, ZSTD_cParameter param, const char* param_name) {
306
+ vibe_zstd_cctx* cctx;
307
+ TypedData_Get_Struct(self, vibe_zstd_cctx, &vibe_zstd_cctx_type, cctx);
308
+
309
+ int value;
310
+ size_t result = ZSTD_CCtx_getParameter(cctx->cctx, param, &value);
311
+ if (ZSTD_isError(result)) {
312
+ rb_raise(rb_eRuntimeError, "Failed to get %s: %s",
313
+ param_name, ZSTD_getErrorName(result));
314
+ }
315
+
316
+ return value ? Qtrue : Qfalse;
317
+ }
318
+
319
+ // Macro to define setter/getter methods for a parameter
320
+ #define DEFINE_CCTX_PARAM_ACCESSORS(rb_name, param_enum, param_str) \
321
+ static VALUE vibe_zstd_cctx_set_##rb_name(VALUE self, VALUE value) { \
322
+ return vibe_zstd_cctx_set_param_generic(self, value, param_enum, param_str); \
323
+ } \
324
+ static VALUE vibe_zstd_cctx_get_##rb_name(VALUE self) { \
325
+ return vibe_zstd_cctx_get_param_generic(self, param_enum, param_str); \
326
+ }
327
+
328
+ // Macro to define setter/getter/predicate methods for boolean parameters
329
+ #define DEFINE_CCTX_PARAM_BOOL_ACCESSORS(rb_name, param_enum, param_str) \
330
+ static VALUE vibe_zstd_cctx_set_##rb_name(VALUE self, VALUE value) { \
331
+ return vibe_zstd_cctx_set_param_bool(self, value, param_enum, param_str); \
332
+ } \
333
+ static VALUE vibe_zstd_cctx_get_##rb_name(VALUE self) { \
334
+ return vibe_zstd_cctx_get_param_bool(self, param_enum, param_str); \
335
+ }
336
+
337
+ // Define all CCtx parameter accessors
338
+ DEFINE_CCTX_PARAM_ACCESSORS(compression_level, ZSTD_c_compressionLevel, "compression_level")
339
+ DEFINE_CCTX_PARAM_ACCESSORS(window_log, ZSTD_c_windowLog, "window_log")
340
+ DEFINE_CCTX_PARAM_ACCESSORS(hash_log, ZSTD_c_hashLog, "hash_log")
341
+ DEFINE_CCTX_PARAM_ACCESSORS(chain_log, ZSTD_c_chainLog, "chain_log")
342
+ DEFINE_CCTX_PARAM_ACCESSORS(search_log, ZSTD_c_searchLog, "search_log")
343
+ DEFINE_CCTX_PARAM_ACCESSORS(min_match, ZSTD_c_minMatch, "min_match")
344
+ DEFINE_CCTX_PARAM_ACCESSORS(target_length, ZSTD_c_targetLength, "target_length")
345
+ DEFINE_CCTX_PARAM_ACCESSORS(strategy, ZSTD_c_strategy, "strategy")
346
+ DEFINE_CCTX_PARAM_ACCESSORS(target_cblock_size, ZSTD_c_targetCBlockSize, "target_cblock_size")
347
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(enable_long_distance_matching, ZSTD_c_enableLongDistanceMatching, "enable_long_distance_matching")
348
+ DEFINE_CCTX_PARAM_ACCESSORS(ldm_hash_log, ZSTD_c_ldmHashLog, "ldm_hash_log")
349
+ DEFINE_CCTX_PARAM_ACCESSORS(ldm_min_match, ZSTD_c_ldmMinMatch, "ldm_min_match")
350
+ DEFINE_CCTX_PARAM_ACCESSORS(ldm_bucket_size_log, ZSTD_c_ldmBucketSizeLog, "ldm_bucket_size_log")
351
+ DEFINE_CCTX_PARAM_ACCESSORS(ldm_hash_rate_log, ZSTD_c_ldmHashRateLog, "ldm_hash_rate_log")
352
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(content_size_flag, ZSTD_c_contentSizeFlag, "content_size_flag")
353
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(checksum_flag, ZSTD_c_checksumFlag, "checksum_flag")
354
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(dict_id_flag, ZSTD_c_dictIDFlag, "dict_id_flag")
355
+ DEFINE_CCTX_PARAM_ACCESSORS(workers, ZSTD_c_nbWorkers, "workers")
356
+ DEFINE_CCTX_PARAM_ACCESSORS(job_size, ZSTD_c_jobSize, "job_size")
357
+ DEFINE_CCTX_PARAM_ACCESSORS(overlap_log, ZSTD_c_overlapLog, "overlap_log")
358
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(rsyncable, ZSTD_c_rsyncable, "rsyncable")
359
+ DEFINE_CCTX_PARAM_ACCESSORS(format, ZSTD_c_format, "format")
360
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(force_max_window, ZSTD_c_forceMaxWindow, "force_max_window")
361
+ DEFINE_CCTX_PARAM_ACCESSORS(force_attach_dict, ZSTD_c_forceAttachDict, "force_attach_dict")
362
+ DEFINE_CCTX_PARAM_ACCESSORS(literal_compression_mode, ZSTD_c_literalCompressionMode, "literal_compression_mode")
363
+ DEFINE_CCTX_PARAM_ACCESSORS(src_size_hint, ZSTD_c_srcSizeHint, "src_size_hint")
364
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(enable_dedicated_dict_search, ZSTD_c_enableDedicatedDictSearch, "enable_dedicated_dict_search")
365
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(stable_in_buffer, ZSTD_c_stableInBuffer, "stable_in_buffer")
366
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(stable_out_buffer, ZSTD_c_stableOutBuffer, "stable_out_buffer")
367
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(block_delimiters, ZSTD_c_blockDelimiters, "block_delimiters")
368
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(validate_sequences, ZSTD_c_validateSequences, "validate_sequences")
369
+ DEFINE_CCTX_PARAM_ACCESSORS(use_row_match_finder, ZSTD_c_useRowMatchFinder, "use_row_match_finder")
370
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(deterministic_ref_prefix, ZSTD_c_deterministicRefPrefix, "deterministic_ref_prefix")
371
+ DEFINE_CCTX_PARAM_ACCESSORS(prefetch_cdict_tables, ZSTD_c_prefetchCDictTables, "prefetch_cdict_tables")
372
+ DEFINE_CCTX_PARAM_BOOL_ACCESSORS(enable_seq_producer_fallback, ZSTD_c_enableSeqProducerFallback, "enable_seq_producer_fallback")
373
+ DEFINE_CCTX_PARAM_ACCESSORS(max_block_size, ZSTD_c_maxBlockSize, "max_block_size")
374
+ DEFINE_CCTX_PARAM_ACCESSORS(search_for_external_repcodes, ZSTD_c_searchForExternalRepcodes, "search_for_external_repcodes")
375
+
376
+ // CCtx parameter_bounds - query parameter bounds (class method, kept for introspection)
377
+ static VALUE
378
+ vibe_zstd_cctx_parameter_bounds(VALUE self, VALUE param_sym) {
379
+ ID symbol_id = SYM2ID(param_sym);
380
+ ZSTD_cParameter param;
381
+ const char* param_name;
382
+
383
+ if (!lookup_cctx_param(symbol_id, &param, &param_name)) {
384
+ rb_raise(rb_eArgError, "Unknown parameter: %s", rb_id2name(symbol_id));
385
+ }
386
+
387
+ ZSTD_bounds bounds = ZSTD_cParam_getBounds(param);
388
+ if (ZSTD_isError(bounds.error)) {
389
+ rb_raise(rb_eRuntimeError, "Failed to get parameter bounds for %s: %s",
390
+ param_name, ZSTD_getErrorName(bounds.error));
391
+ }
392
+
393
+ VALUE result = rb_hash_new();
394
+ rb_hash_aset(result, ID2SYM(rb_intern("min")), INT2NUM(bounds.lowerBound));
395
+ rb_hash_aset(result, ID2SYM(rb_intern("max")), INT2NUM(bounds.upperBound));
396
+ return result;
397
+ }
398
+
399
+ // CCtx use_prefix - use raw data as prefix (lightweight dictionary)
400
+ static VALUE
401
+ vibe_zstd_cctx_use_prefix(VALUE self, VALUE prefix_data) {
402
+ vibe_zstd_cctx* cctx;
403
+ TypedData_Get_Struct(self, vibe_zstd_cctx, &vibe_zstd_cctx_type, cctx);
404
+
405
+ StringValue(prefix_data);
406
+
407
+ size_t result = ZSTD_CCtx_refPrefix(cctx->cctx, RSTRING_PTR(prefix_data), RSTRING_LEN(prefix_data));
408
+
409
+ if (ZSTD_isError(result)) {
410
+ rb_raise(rb_eRuntimeError, "Failed to set prefix: %s", ZSTD_getErrorName(result));
411
+ }
412
+
413
+ return self;
414
+ }
415
+
416
+ // CCtx reset - reset context to clean state
417
+ static VALUE
418
+ vibe_zstd_cctx_reset(int argc, VALUE* argv, VALUE self) {
419
+ VALUE reset_mode;
420
+ rb_scan_args(argc, argv, "01", &reset_mode);
421
+
422
+ vibe_zstd_cctx* cctx;
423
+ TypedData_Get_Struct(self, vibe_zstd_cctx, &vibe_zstd_cctx_type, cctx);
424
+
425
+ // Default to SESSION_AND_PARAMETERS if no argument provided
426
+ ZSTD_ResetDirective directive = ZSTD_reset_session_and_parameters;
427
+
428
+ if (!NIL_P(reset_mode)) {
429
+ int mode = NUM2INT(reset_mode);
430
+ if (mode == ZSTD_reset_session_only) {
431
+ directive = ZSTD_reset_session_only;
432
+ } else if (mode == ZSTD_reset_parameters) {
433
+ directive = ZSTD_reset_parameters;
434
+ } else if (mode == ZSTD_reset_session_and_parameters) {
435
+ directive = ZSTD_reset_session_and_parameters;
436
+ } else {
437
+ rb_raise(rb_eArgError, "Invalid reset_mode %d: must be ResetDirective::SESSION (1), PARAMETERS (2), or BOTH (3)", mode);
438
+ }
439
+ }
440
+
441
+ size_t result = ZSTD_CCtx_reset(cctx->cctx, directive);
442
+
443
+ if (ZSTD_isError(result)) {
444
+ rb_raise(rb_eRuntimeError, "Failed to reset compression context: %s", ZSTD_getErrorName(result));
445
+ }
446
+
447
+ return self;
448
+ }
449
+
450
+ // Class initialization function called from main Init_vibe_zstd
451
+ void
452
+ vibe_zstd_cctx_init_class(VALUE rb_cVibeZstdCCtx) {
453
+ // Initialize parameter lookup table
454
+ init_cctx_param_table();
455
+
456
+ // Define allocation and basic methods
457
+ rb_define_alloc_func(rb_cVibeZstdCCtx, vibe_zstd_cctx_alloc);
458
+ rb_define_method(rb_cVibeZstdCCtx, "initialize", vibe_zstd_cctx_initialize, -1);
459
+ rb_define_method(rb_cVibeZstdCCtx, "compress", vibe_zstd_cctx_compress, -1);
460
+ rb_define_method(rb_cVibeZstdCCtx, "use_prefix", vibe_zstd_cctx_use_prefix, 1);
461
+ rb_define_method(rb_cVibeZstdCCtx, "reset", vibe_zstd_cctx_reset, -1);
462
+ rb_define_singleton_method(rb_cVibeZstdCCtx, "parameter_bounds", vibe_zstd_cctx_parameter_bounds, 1);
463
+ rb_define_singleton_method(rb_cVibeZstdCCtx, "estimate_memory", vibe_zstd_cctx_estimate_memory, 1);
464
+
465
+ // CCtx parameter accessors
466
+ rb_define_method(rb_cVibeZstdCCtx, "compression_level=", vibe_zstd_cctx_set_compression_level, 1);
467
+ rb_define_method(rb_cVibeZstdCCtx, "compression_level", vibe_zstd_cctx_get_compression_level, 0);
468
+ rb_define_alias(rb_cVibeZstdCCtx, "level=", "compression_level=");
469
+ rb_define_alias(rb_cVibeZstdCCtx, "level", "compression_level");
470
+ rb_define_method(rb_cVibeZstdCCtx, "window_log=", vibe_zstd_cctx_set_window_log, 1);
471
+ rb_define_method(rb_cVibeZstdCCtx, "window_log", vibe_zstd_cctx_get_window_log, 0);
472
+ rb_define_method(rb_cVibeZstdCCtx, "hash_log=", vibe_zstd_cctx_set_hash_log, 1);
473
+ rb_define_method(rb_cVibeZstdCCtx, "hash_log", vibe_zstd_cctx_get_hash_log, 0);
474
+ rb_define_method(rb_cVibeZstdCCtx, "chain_log=", vibe_zstd_cctx_set_chain_log, 1);
475
+ rb_define_method(rb_cVibeZstdCCtx, "chain_log", vibe_zstd_cctx_get_chain_log, 0);
476
+ rb_define_method(rb_cVibeZstdCCtx, "search_log=", vibe_zstd_cctx_set_search_log, 1);
477
+ rb_define_method(rb_cVibeZstdCCtx, "search_log", vibe_zstd_cctx_get_search_log, 0);
478
+ rb_define_method(rb_cVibeZstdCCtx, "min_match=", vibe_zstd_cctx_set_min_match, 1);
479
+ rb_define_method(rb_cVibeZstdCCtx, "min_match", vibe_zstd_cctx_get_min_match, 0);
480
+ rb_define_method(rb_cVibeZstdCCtx, "target_length=", vibe_zstd_cctx_set_target_length, 1);
481
+ rb_define_method(rb_cVibeZstdCCtx, "target_length", vibe_zstd_cctx_get_target_length, 0);
482
+ rb_define_method(rb_cVibeZstdCCtx, "strategy=", vibe_zstd_cctx_set_strategy, 1);
483
+ rb_define_method(rb_cVibeZstdCCtx, "strategy", vibe_zstd_cctx_get_strategy, 0);
484
+ rb_define_method(rb_cVibeZstdCCtx, "target_cblock_size=", vibe_zstd_cctx_set_target_cblock_size, 1);
485
+ rb_define_method(rb_cVibeZstdCCtx, "target_cblock_size", vibe_zstd_cctx_get_target_cblock_size, 0);
486
+ rb_define_method(rb_cVibeZstdCCtx, "enable_long_distance_matching=", vibe_zstd_cctx_set_enable_long_distance_matching, 1);
487
+ rb_define_method(rb_cVibeZstdCCtx, "enable_long_distance_matching", vibe_zstd_cctx_get_enable_long_distance_matching, 0);
488
+ rb_define_alias(rb_cVibeZstdCCtx, "long_distance_matching=", "enable_long_distance_matching=");
489
+ rb_define_alias(rb_cVibeZstdCCtx, "long_distance_matching", "enable_long_distance_matching");
490
+ rb_define_alias(rb_cVibeZstdCCtx, "long_distance_matching?", "enable_long_distance_matching");
491
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_hash_log=", vibe_zstd_cctx_set_ldm_hash_log, 1);
492
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_hash_log", vibe_zstd_cctx_get_ldm_hash_log, 0);
493
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_min_match=", vibe_zstd_cctx_set_ldm_min_match, 1);
494
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_min_match", vibe_zstd_cctx_get_ldm_min_match, 0);
495
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_bucket_size_log=", vibe_zstd_cctx_set_ldm_bucket_size_log, 1);
496
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_bucket_size_log", vibe_zstd_cctx_get_ldm_bucket_size_log, 0);
497
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_hash_rate_log=", vibe_zstd_cctx_set_ldm_hash_rate_log, 1);
498
+ rb_define_method(rb_cVibeZstdCCtx, "ldm_hash_rate_log", vibe_zstd_cctx_get_ldm_hash_rate_log, 0);
499
+ rb_define_method(rb_cVibeZstdCCtx, "content_size_flag=", vibe_zstd_cctx_set_content_size_flag, 1);
500
+ rb_define_method(rb_cVibeZstdCCtx, "content_size_flag", vibe_zstd_cctx_get_content_size_flag, 0);
501
+ rb_define_method(rb_cVibeZstdCCtx, "checksum_flag=", vibe_zstd_cctx_set_checksum_flag, 1);
502
+ rb_define_method(rb_cVibeZstdCCtx, "checksum_flag", vibe_zstd_cctx_get_checksum_flag, 0);
503
+ rb_define_method(rb_cVibeZstdCCtx, "dict_id_flag=", vibe_zstd_cctx_set_dict_id_flag, 1);
504
+ rb_define_method(rb_cVibeZstdCCtx, "dict_id_flag", vibe_zstd_cctx_get_dict_id_flag, 0);
505
+
506
+ // Boolean aliases without _flag suffix and predicate methods
507
+ rb_define_alias(rb_cVibeZstdCCtx, "checksum=", "checksum_flag=");
508
+ rb_define_alias(rb_cVibeZstdCCtx, "checksum", "checksum_flag");
509
+ rb_define_alias(rb_cVibeZstdCCtx, "checksum?", "checksum_flag");
510
+ rb_define_alias(rb_cVibeZstdCCtx, "content_size=", "content_size_flag=");
511
+ rb_define_alias(rb_cVibeZstdCCtx, "content_size", "content_size_flag");
512
+ rb_define_alias(rb_cVibeZstdCCtx, "content_size?", "content_size_flag");
513
+ rb_define_alias(rb_cVibeZstdCCtx, "dict_id=", "dict_id_flag=");
514
+ rb_define_alias(rb_cVibeZstdCCtx, "dict_id", "dict_id_flag");
515
+ rb_define_alias(rb_cVibeZstdCCtx, "dict_id?", "dict_id_flag");
516
+ rb_define_method(rb_cVibeZstdCCtx, "workers=", vibe_zstd_cctx_set_workers, 1);
517
+ rb_define_method(rb_cVibeZstdCCtx, "workers", vibe_zstd_cctx_get_workers, 0);
518
+ rb_define_method(rb_cVibeZstdCCtx, "job_size=", vibe_zstd_cctx_set_job_size, 1);
519
+ rb_define_method(rb_cVibeZstdCCtx, "job_size", vibe_zstd_cctx_get_job_size, 0);
520
+ rb_define_method(rb_cVibeZstdCCtx, "overlap_log=", vibe_zstd_cctx_set_overlap_log, 1);
521
+ rb_define_method(rb_cVibeZstdCCtx, "overlap_log", vibe_zstd_cctx_get_overlap_log, 0);
522
+ rb_define_method(rb_cVibeZstdCCtx, "rsyncable=", vibe_zstd_cctx_set_rsyncable, 1);
523
+ rb_define_method(rb_cVibeZstdCCtx, "rsyncable", vibe_zstd_cctx_get_rsyncable, 0);
524
+ rb_define_alias(rb_cVibeZstdCCtx, "rsyncable?", "rsyncable");
525
+ rb_define_method(rb_cVibeZstdCCtx, "format=", vibe_zstd_cctx_set_format, 1);
526
+ rb_define_method(rb_cVibeZstdCCtx, "format", vibe_zstd_cctx_get_format, 0);
527
+ rb_define_method(rb_cVibeZstdCCtx, "force_max_window=", vibe_zstd_cctx_set_force_max_window, 1);
528
+ rb_define_method(rb_cVibeZstdCCtx, "force_max_window", vibe_zstd_cctx_get_force_max_window, 0);
529
+ rb_define_alias(rb_cVibeZstdCCtx, "force_max_window?", "force_max_window");
530
+ rb_define_method(rb_cVibeZstdCCtx, "force_attach_dict=", vibe_zstd_cctx_set_force_attach_dict, 1);
531
+ rb_define_method(rb_cVibeZstdCCtx, "force_attach_dict", vibe_zstd_cctx_get_force_attach_dict, 0);
532
+ rb_define_method(rb_cVibeZstdCCtx, "literal_compression_mode=", vibe_zstd_cctx_set_literal_compression_mode, 1);
533
+ rb_define_method(rb_cVibeZstdCCtx, "literal_compression_mode", vibe_zstd_cctx_get_literal_compression_mode, 0);
534
+ rb_define_method(rb_cVibeZstdCCtx, "src_size_hint=", vibe_zstd_cctx_set_src_size_hint, 1);
535
+ rb_define_method(rb_cVibeZstdCCtx, "src_size_hint", vibe_zstd_cctx_get_src_size_hint, 0);
536
+ rb_define_method(rb_cVibeZstdCCtx, "enable_dedicated_dict_search=", vibe_zstd_cctx_set_enable_dedicated_dict_search, 1);
537
+ rb_define_method(rb_cVibeZstdCCtx, "enable_dedicated_dict_search", vibe_zstd_cctx_get_enable_dedicated_dict_search, 0);
538
+ rb_define_alias(rb_cVibeZstdCCtx, "enable_dedicated_dict_search?", "enable_dedicated_dict_search");
539
+ rb_define_method(rb_cVibeZstdCCtx, "stable_in_buffer=", vibe_zstd_cctx_set_stable_in_buffer, 1);
540
+ rb_define_method(rb_cVibeZstdCCtx, "stable_in_buffer", vibe_zstd_cctx_get_stable_in_buffer, 0);
541
+ rb_define_alias(rb_cVibeZstdCCtx, "stable_in_buffer?", "stable_in_buffer");
542
+ rb_define_method(rb_cVibeZstdCCtx, "stable_out_buffer=", vibe_zstd_cctx_set_stable_out_buffer, 1);
543
+ rb_define_method(rb_cVibeZstdCCtx, "stable_out_buffer", vibe_zstd_cctx_get_stable_out_buffer, 0);
544
+ rb_define_alias(rb_cVibeZstdCCtx, "stable_out_buffer?", "stable_out_buffer");
545
+ rb_define_method(rb_cVibeZstdCCtx, "block_delimiters=", vibe_zstd_cctx_set_block_delimiters, 1);
546
+ rb_define_method(rb_cVibeZstdCCtx, "block_delimiters", vibe_zstd_cctx_get_block_delimiters, 0);
547
+ rb_define_alias(rb_cVibeZstdCCtx, "block_delimiters?", "block_delimiters");
548
+ rb_define_method(rb_cVibeZstdCCtx, "validate_sequences=", vibe_zstd_cctx_set_validate_sequences, 1);
549
+ rb_define_method(rb_cVibeZstdCCtx, "validate_sequences", vibe_zstd_cctx_get_validate_sequences, 0);
550
+ rb_define_alias(rb_cVibeZstdCCtx, "validate_sequences?", "validate_sequences");
551
+ rb_define_method(rb_cVibeZstdCCtx, "use_row_match_finder=", vibe_zstd_cctx_set_use_row_match_finder, 1);
552
+ rb_define_method(rb_cVibeZstdCCtx, "use_row_match_finder", vibe_zstd_cctx_get_use_row_match_finder, 0);
553
+ rb_define_method(rb_cVibeZstdCCtx, "deterministic_ref_prefix=", vibe_zstd_cctx_set_deterministic_ref_prefix, 1);
554
+ rb_define_method(rb_cVibeZstdCCtx, "deterministic_ref_prefix", vibe_zstd_cctx_get_deterministic_ref_prefix, 0);
555
+ rb_define_alias(rb_cVibeZstdCCtx, "deterministic_ref_prefix?", "deterministic_ref_prefix");
556
+ rb_define_method(rb_cVibeZstdCCtx, "prefetch_cdict_tables=", vibe_zstd_cctx_set_prefetch_cdict_tables, 1);
557
+ rb_define_method(rb_cVibeZstdCCtx, "prefetch_cdict_tables", vibe_zstd_cctx_get_prefetch_cdict_tables, 0);
558
+ rb_define_method(rb_cVibeZstdCCtx, "enable_seq_producer_fallback=", vibe_zstd_cctx_set_enable_seq_producer_fallback, 1);
559
+ rb_define_method(rb_cVibeZstdCCtx, "enable_seq_producer_fallback", vibe_zstd_cctx_get_enable_seq_producer_fallback, 0);
560
+ rb_define_alias(rb_cVibeZstdCCtx, "enable_seq_producer_fallback?", "enable_seq_producer_fallback");
561
+ rb_define_method(rb_cVibeZstdCCtx, "max_block_size=", vibe_zstd_cctx_set_max_block_size, 1);
562
+ rb_define_method(rb_cVibeZstdCCtx, "max_block_size", vibe_zstd_cctx_get_max_block_size, 0);
563
+ rb_define_method(rb_cVibeZstdCCtx, "search_for_external_repcodes=", vibe_zstd_cctx_set_search_for_external_repcodes, 1);
564
+ rb_define_method(rb_cVibeZstdCCtx, "search_for_external_repcodes", vibe_zstd_cctx_get_search_for_external_repcodes, 0);
565
+ }