Module: Zstandard::API
- Defined in:
- lib/zstandard/api.rb
Overview
Internal API layer to abstract different libzstd calling semantics/versions
Class Method Summary collapse
-
.decompressed_size(string) ⇒ Integer
Tries to gather the size of the decompressed data.
- .simple_compress(string, options = {}) ⇒ Object
- .simple_decompress(string, options = {}) ⇒ Object
- .streaming_decompress(string, options = {}) ⇒ Object
- .window_size(string) ⇒ Object
Class Method Details
.decompressed_size(string) ⇒ Integer
Tries to gather the size of the decompressed data.
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/zstandard/api.rb', line 56 def self.decompressed_size(string) if FFIBindings.zstd_version_number < 600 parameters = FFIBindings::ZSTD_parameters.new FFIBindings.zstd_get_frame_params(parameters, string, string.bytesize) parameters[:srcSize] elsif FFIBindings.zstd_version_number < 10104 frame_params = FFIBindings::ZSTD_frameParams.new FFIBindings.zstd_get_frame_params(frame_params, string, string.bytesize) frame_params[:frameContentSize] else FFIBindings.zstd_find_decompressed_size(string, string.bytesize) end end |
.simple_compress(string, options = {}) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/zstandard/api.rb', line 70 def self.simple_compress(string, = {}) level = [:level] || 1 dst_size = FFIBindings.zstd_compress_bound(string.bytesize) dst = FFI::MemoryPointer.new(:char, dst_size) error_code = number_of_bytes = FFIBindings.zstd_compress(dst, dst_size, string, string.bytesize, level) if FFIBindings.zstd_is_error(error_code) >= 0 dst.read_bytes(number_of_bytes) else raise "error" end end |
.simple_decompress(string, options = {}) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/zstandard/api.rb', line 85 def self.simple_decompress(string, = {}) # # The docs state, that one should be carefull when using the simple decompress API, because # it relies on the upfront knowledge of the decompressed (dst) size. This information may # by present within the frame header (or not). If it's present, it can be very large and/or # intentionally modified, so it's vital to check that this value is within the systems limits # and fallback to streaming decompression if unsure. # dst = FFI::MemoryPointer.new(:char, dst_size = API.decompressed_size(string)) error_code = number_of_bytes = FFIBindings.zstd_decompress(dst, dst_size, string, string.bytesize) if FFIBindings.zstd_is_error(error_code) != 0 raise FFIBindings.zstd_get_error_name(error_code).read_string else dst.read_bytes(number_of_bytes) end end |
.streaming_decompress(string, options = {}) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/zstandard/api.rb', line 7 def self.streaming_decompress(string, = {}) dst_size = window_size(string) # The docs propose to check the dst size (windowSize), because it could be manipulated raise "Invalid dst size!" if dst_size <= 0 || dst_size > Config::MAX_STREAMING_DECOMRPESS_BUFFER_SIZE src = FFI::MemoryPointer.from_string(string) # we need the pointer for arithmetics dst = FFI::MemoryPointer.new(:char, dst_size) dst_offset = 0 src_offset = 0 result = [] dctx = FFIBindings.zstd_create_dctx FFIBindings.zstd_decompress_begin(dctx) while (src_size = FFIBindings.zstd_next_src_size_to_deompress(dctx)) != 0 nbytes = FFIBindings.zstd_decompress_continue( dctx, dst + dst_offset, (dst + dst_offset).size, src + src_offset, src_size ) if FFIBindings.zstd_is_error(error_code = nbytes) > 0 raise FFIBindings.zstd_get_error_name(error_code) elsif nbytes > 0 result << (dst + dst_offset).read_bytes(nbytes) dst_offset += nbytes dst_offset = 0 if (dst + dst_offset).size == 0 end src_offset += src_size end dst.free src.free FFIBindings.zstd_free_dctx(dctx) result.join end |
.window_size(string) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/zstandard/api.rb', line 103 def self.window_size(string) if FFIBindings.zstd_version_number < 600 parameters = FFIBindings::ZSTD_parameters.new FFIBindings.zstd_get_frame_params(parameters, string, string.bytesize) 2 ** parameters[:windowLog] elsif FFIBindings.zstd_version_number < 700 frame_params = FFIBindings::ZSTD_frameParams.new FFIBindings.zstd_get_frame_params(frame_params, string, string.bytesize) 2 ** frame_params[:windowLog] elsif Zstandard::FFIBindings.zstd_version_number < 10300 frame_params = FFIBindings::ZSTD_frameParams.new FFIBindings.zstd_get_frame_params(frame_params, string, string.bytesize) frame_params[:windowSize] else frame_header = FFIBindings::ZSTD_frameHeader.new FFIBindings.zstd_get_frame_header(frame_header, string, string.bytesize) frame_header[:windowSize] end end |