module Zstandard::API
Internal API
layer to abstract different libzstd calling semantics/versions
Public Class Methods
decompressed_size(string)
click to toggle source
Tries to gather the size of the decompressed data.
@param [String] string Compressed data @return [Integer] size of the decompressed data or 0
# 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 = {})
click to toggle source
# File lib/zstandard/api.rb, line 70 def self.simple_compress(string, options = {}) level = options[:level] || 0 # 0 means default 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 = {})
click to toggle source
# File lib/zstandard/api.rb, line 85 def self.simple_decompress(string, options = {}) # # 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 = {})
click to toggle source
# File lib/zstandard/api.rb, line 7 def self.streaming_decompress(string, options = {}) 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)
click to toggle source
# 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