omnizip 0.4.3 → 0.4.4
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/lib/omnizip/algorithms/deflate.rb +7 -2
- data/lib/omnizip/algorithms/deflate64.rb +13 -12
- data/lib/omnizip/algorithms/zstandard.rb +7 -2
- data/lib/omnizip/backends.rb +23 -10
- data/lib/omnizip/implementations/rust/library.rb +3 -3
- data/lib/omnizip/implementations/rust.rb +5 -5
- data/lib/omnizip/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8cf4c62c7304ef792b48b96486685707c68010f0cc6529b6a7504454b94ea025
|
|
4
|
+
data.tar.gz: 7c0d5e62fc21a99ccc85520ee0cd3ea32afaae39e76f10826dd56697ffa8376b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 539124e9189208423daacdac7cad6735f4a1069358a6ee7e39bb09155524589a2b1a01a6b1c41af6b650648dee327b2c4d36e71ccbbba5ff5e4453168f6ec9ef
|
|
7
|
+
data.tar.gz: 02ae0fdb9844f006e5289d8bd351b4ac023e8fafd704bd6fc96b6a0489bc27c96d3e7d3e32ef06011a8123b37573d877191e93cdbaa7c0f6e63e139e8485c09e
|
|
@@ -68,8 +68,13 @@ module Omnizip
|
|
|
68
68
|
# @return [void]
|
|
69
69
|
def compress(input_stream, output_stream, options = nil)
|
|
70
70
|
input_data = input_stream.read
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
level = build_encoder_options(options)[:level] || 6
|
|
72
|
+
output_stream.write(
|
|
73
|
+
Backends.compress("zlib", input_data, level) do
|
|
74
|
+
encoder = Encoder.new(output_stream, build_encoder_options(options))
|
|
75
|
+
encoder.encode_stream(input_data)
|
|
76
|
+
end,
|
|
77
|
+
)
|
|
73
78
|
end
|
|
74
79
|
|
|
75
80
|
# Decompress Deflate-compressed data
|
|
@@ -42,21 +42,22 @@ module Omnizip
|
|
|
42
42
|
# @param options [Hash] Compression options
|
|
43
43
|
# @option options [Integer] :level Compression level (1-9)
|
|
44
44
|
def compress(input, output, options = {})
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
raw_level = options[:level] || Zlib::DEFAULT_COMPRESSION
|
|
47
46
|
data = input.read
|
|
48
47
|
return if data.nil? || data.empty?
|
|
49
48
|
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Zlib::
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
# Zlib::DEFAULT_COMPRESSION (-1) maps to the FFI's 6.
|
|
50
|
+
level = raw_level.negative? ? 6 : raw_level.clamp(0, 9)
|
|
51
|
+
compressed = Backends.compress("zlib", data, level) do
|
|
52
|
+
deflater = Zlib::Deflate.new(
|
|
53
|
+
raw_level,
|
|
54
|
+
Zlib::MAX_WBITS,
|
|
55
|
+
Zlib::MAX_MEM_LEVEL,
|
|
56
|
+
)
|
|
57
|
+
result = deflater.deflate(data, Zlib::FINISH)
|
|
58
|
+
deflater.close
|
|
59
|
+
result
|
|
60
|
+
end
|
|
60
61
|
output.write(compressed)
|
|
61
62
|
end
|
|
62
63
|
|
|
@@ -86,8 +86,13 @@ module Omnizip
|
|
|
86
86
|
# @return [void]
|
|
87
87
|
def compress(input_stream, output_stream, options = nil)
|
|
88
88
|
input_data = input_stream.read
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
level = build_encoder_options(options)[:level] || 3
|
|
90
|
+
output_stream.write(
|
|
91
|
+
Backends.compress("zstd", input_data, level) do
|
|
92
|
+
encoder = Encoder.new(output_stream, build_encoder_options(options))
|
|
93
|
+
encoder.encode_stream(input_data)
|
|
94
|
+
end,
|
|
95
|
+
)
|
|
91
96
|
end
|
|
92
97
|
|
|
93
98
|
# Decompress Zstandard-compressed data
|
data/lib/omnizip/backends.rb
CHANGED
|
@@ -27,19 +27,23 @@ module Omnizip
|
|
|
27
27
|
# over frame stability.
|
|
28
28
|
module Backends
|
|
29
29
|
# Codecs whose Rust encoder is BYTE-IDENTICAL to the pure-Ruby
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
|
|
30
|
+
# 2026-09-20 policy flip (owner directive): RUST IS THE AUTHORITY
|
|
31
|
+
# — its encoders/decoders are the ports validated against the
|
|
32
|
+
# reference C/C++ implementations (bzip2, xz/liblzma, zstd,
|
|
33
|
+
# libdeflate), and they are determinism-contracted (same input +
|
|
34
|
+
# level => same bytes on every machine). :auto therefore routes
|
|
35
|
+
# BOTH directions through Rust whenever the cdylib loads; encode
|
|
36
|
+
# falls back to the Ruby core on any Rust error, so :auto is
|
|
37
|
+
# never worse than pure Ruby. The pure-Ruby cores remain the
|
|
38
|
+
# portable fallback and the OMNIZIP_BACKEND=ruby escape hatch.
|
|
39
|
+
RUST_AUTHORITATIVE = true
|
|
36
40
|
|
|
37
41
|
# usize::MAX — the FFI's "caller does not know the plaintext
|
|
38
42
|
# size" sentinel (streaming decode contract).
|
|
39
43
|
UNKNOWN_LENGTH = 0xFFFF_FFFF_FFFF_FFFF
|
|
40
44
|
|
|
41
45
|
class << self
|
|
42
|
-
def for(codec,
|
|
46
|
+
def for(codec, _direction)
|
|
43
47
|
mode = ENV.fetch("OMNIZIP_BACKEND", "auto")
|
|
44
48
|
|
|
45
49
|
return backend_rust if mode == "rust"
|
|
@@ -48,17 +52,26 @@ module Omnizip
|
|
|
48
52
|
return backend_ruby unless Implementations::Rust::Library.available?
|
|
49
53
|
return backend_ruby unless Implementations::Rust::Library::CODECS.include?(codec)
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
backend_rust
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
# Compress through the tier-selected backend. The block is
|
|
55
59
|
# the pure-Ruby core — evaluated ONLY on the Ruby path, so
|
|
56
|
-
# the accelerated path never pays for it.
|
|
60
|
+
# the accelerated path never pays for it. A Rust encode error
|
|
61
|
+
# falls back to the Ruby core (auto is never worse than pure
|
|
62
|
+
# Ruby); only the forced `rust` mode propagates.
|
|
57
63
|
def compress(codec, data, level, &ruby_core)
|
|
58
64
|
backend = Backends.for(codec, :encode)
|
|
59
65
|
return yield if backend == RubyBackend
|
|
60
66
|
|
|
61
|
-
|
|
67
|
+
begin
|
|
68
|
+
backend.compress(codec, data, level)
|
|
69
|
+
rescue Implementations::Rust::Error => e
|
|
70
|
+
raise if ENV.fetch("OMNIZIP_BACKEND", "auto") == "rust"
|
|
71
|
+
|
|
72
|
+
warn "omnizip: rust #{codec} encode failed (#{e.message}); using ruby" if ENV["OMNIZIP_BACKEND_DEBUG"]
|
|
73
|
+
yield
|
|
74
|
+
end
|
|
62
75
|
end
|
|
63
76
|
|
|
64
77
|
# Decompress through the tier-selected backend (output-
|
|
@@ -16,9 +16,9 @@ module Omnizip
|
|
|
16
16
|
# built; compress/decompress are pure C calls).
|
|
17
17
|
class Library
|
|
18
18
|
# Codecs the cdylib dispatches by name.
|
|
19
|
-
# Names the cdylib dispatches: the codec-level acceleration
|
|
20
|
-
# (
|
|
21
|
-
#
|
|
19
|
+
# Names the cdylib dispatches: the codec-level acceleration
|
|
20
|
+
# surface (both directions by default — Rust is the
|
|
21
|
+
# authority; Ruby is the fallback).
|
|
22
22
|
CODECS = %w[
|
|
23
23
|
bzip2 zstd lzma xz lzma-alone lzip
|
|
24
24
|
deflate deflate64 zlib gzip
|
|
@@ -13,11 +13,11 @@ module Omnizip
|
|
|
13
13
|
# 1. ENV['OMNIZIP_FFI_DYLIB'] (explicit path)
|
|
14
14
|
# 2. ../target/release/ inside a sibling omnizip-rs checkout
|
|
15
15
|
#
|
|
16
|
-
# Tier policy (see Omnizip::Backends):
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
16
|
+
# Tier policy (see Omnizip::Backends): Rust is the authority —
|
|
17
|
+
# validated against the reference C/C++ implementations and
|
|
18
|
+
# determinism-contracted — so `auto` routes BOTH directions
|
|
19
|
+
# through Rust whenever the library loads, with Ruby-core
|
|
20
|
+
# fallback on any Rust error.
|
|
21
21
|
module Rust
|
|
22
22
|
autoload :Library, "omnizip/implementations/rust/library"
|
|
23
23
|
end
|
data/lib/omnizip/version.rb
CHANGED