Class: VibeZstd::CompressWriter

Inherits:
Object
  • Object
show all
Defined in:
lib/vibe_zstd.rb,
ext/vibe_zstd/vibe_zstd.c

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.open(io, **options) ⇒ Object

Block-based resource management Automatically calls finish when block completes



190
191
192
193
194
195
196
197
198
199
# File 'lib/vibe_zstd.rb', line 190

def self.open(io, **options)
  writer = new(io, **options)
  return writer unless block_given?

  begin
    yield writer
  ensure
    writer.finish
  end
end

Instance Method Details

#closeObject

alias



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'ext/vibe_zstd/streaming.c', line 225

static VALUE
vibe_zstd_writer_finish(VALUE self) {
    vibe_zstd_cstream* cstream;
    TypedData_Get_Struct(self, vibe_zstd_cstream, &vibe_zstd_cstream_type, cstream);

    size_t outBufferSize = ZSTD_CStreamOutSize();
    VALUE outBuffer = cstream->output_buffer;

    ZSTD_inBuffer input = { NULL, 0, 0 };
    size_t remaining;

    // ZSTD_e_end: finalize frame with checksum and epilogue
    // Loop until remaining == 0 (frame complete)
    do {
        rb_str_modify(outBuffer);
        rb_str_resize(outBuffer, (long)outBufferSize);
        rb_str_set_len(outBuffer, 0);
        ZSTD_outBuffer output = {
            .dst = RSTRING_PTR(outBuffer),
            .size = outBufferSize,
            .pos = 0
        };

        // Return value > 0 means more epilogue data to write
        remaining = ZSTD_compressStream2((ZSTD_CCtx*)cstream->cstream, &output, &input, ZSTD_e_end);
        if (ZSTD_isError(remaining)) {
            rb_raise(rb_eRuntimeError, "Finish failed: %s", ZSTD_getErrorName(remaining));
        }

        if (output.pos > 0) {
            rb_str_set_len(outBuffer, output.pos);
            rb_funcall(cstream->io, id_write, 1, outBuffer);
        }
    } while (remaining > 0);

    return self;
}

#finishObject



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'ext/vibe_zstd/streaming.c', line 225

static VALUE
vibe_zstd_writer_finish(VALUE self) {
    vibe_zstd_cstream* cstream;
    TypedData_Get_Struct(self, vibe_zstd_cstream, &vibe_zstd_cstream_type, cstream);

    size_t outBufferSize = ZSTD_CStreamOutSize();
    VALUE outBuffer = cstream->output_buffer;

    ZSTD_inBuffer input = { NULL, 0, 0 };
    size_t remaining;

    // ZSTD_e_end: finalize frame with checksum and epilogue
    // Loop until remaining == 0 (frame complete)
    do {
        rb_str_modify(outBuffer);
        rb_str_resize(outBuffer, (long)outBufferSize);
        rb_str_set_len(outBuffer, 0);
        ZSTD_outBuffer output = {
            .dst = RSTRING_PTR(outBuffer),
            .size = outBufferSize,
            .pos = 0
        };

        // Return value > 0 means more epilogue data to write
        remaining = ZSTD_compressStream2((ZSTD_CCtx*)cstream->cstream, &output, &input, ZSTD_e_end);
        if (ZSTD_isError(remaining)) {
            rb_raise(rb_eRuntimeError, "Finish failed: %s", ZSTD_getErrorName(remaining));
        }

        if (output.pos > 0) {
            rb_str_set_len(outBuffer, output.pos);
            rb_funcall(cstream->io, id_write, 1, outBuffer);
        }
    } while (remaining > 0);

    return self;
}

#flushObject



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'ext/vibe_zstd/streaming.c', line 187

static VALUE
vibe_zstd_writer_flush(VALUE self) {
    vibe_zstd_cstream* cstream;
    TypedData_Get_Struct(self, vibe_zstd_cstream, &vibe_zstd_cstream_type, cstream);

    size_t outBufferSize = ZSTD_CStreamOutSize();
    VALUE outBuffer = cstream->output_buffer;

    ZSTD_inBuffer input = { NULL, 0, 0 };
    size_t remaining;

    // ZSTD_e_flush: flush internal buffers, making all data readable
    // Loop until remaining == 0 (flush complete)
    do {
        rb_str_modify(outBuffer);
        rb_str_resize(outBuffer, (long)outBufferSize);
        rb_str_set_len(outBuffer, 0);
        ZSTD_outBuffer output = {
            .dst = RSTRING_PTR(outBuffer),
            .size = outBufferSize,
            .pos = 0
        };

        // Return value > 0 means more flushing needed
        remaining = ZSTD_compressStream2((ZSTD_CCtx*)cstream->cstream, &output, &input, ZSTD_e_flush);
        if (ZSTD_isError(remaining)) {
            rb_raise(rb_eRuntimeError, "Flush failed: %s", ZSTD_getErrorName(remaining));
        }

        if (output.pos > 0) {
            rb_str_set_len(outBuffer, output.pos);
            rb_funcall(cstream->io, id_write, 1, outBuffer);
        }
    } while (remaining > 0);

    return self;
}

#write(data) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'ext/vibe_zstd/streaming.c', line 167

static VALUE
vibe_zstd_writer_write(VALUE self, VALUE data) {
    Check_Type(data, T_STRING);

    vibe_zstd_cstream* cstream;
    TypedData_Get_Struct(self, vibe_zstd_cstream, &vibe_zstd_cstream_type, cstream);

    // Lock data for the duration of the compress loop so that RSTRING_PTR(data)
    // stays valid even when io.write (called inside the loop) runs Ruby code that
    // could otherwise mutate or resize the string.  rb_str_locktmp raises if the
    // string is already locked; the ensure always unlocks it.
    rb_str_locktmp(data);

    vibe_zstd_write_state state = { cstream, data };
    rb_ensure(vibe_zstd_writer_write_body, (VALUE)&state,
              vibe_zstd_writer_write_unlock, data);

    return self;
}