zrip 0.1.2 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a2a6ebe092e7300362703f683d2716ffc66750bd51e4b4f9cd62d1e6aef1a5c
4
- data.tar.gz: ea416eb330e63ba0f228bc2f5cf43f217d03f5e87cf57df0c6c0ae5c4e9c4e11
3
+ metadata.gz: 8a16cab574ece332812f7e25c48b75152a11c63418619527273e974353c7279b
4
+ data.tar.gz: 9504303323b72ca6b079ddcb528a3be99d550a56125241c669613221d5aea4e7
5
5
  SHA512:
6
- metadata.gz: 5b5a2ee2834a146ccd72b7c08bbf20fbe60409377055bf4be840338baa3101f21fd3fc800e5bf2faee5fc211600ea5d853088d9f78702e59876acd0fcc18cf27
7
- data.tar.gz: 25ecf73ec1e2d9874672ef06f4fc55e5e9a09eb522b1c3c55c4ee87032d4572330725c555fd54e4314f4e3454f78daf076ebac43ddeb03c44014d9d79d7e1d57
6
+ metadata.gz: f80dfc72c92ce4a072d186ba75efa88f88281aab64cc94a19d15e3e15f1548aa52fa7b9cec4d7593db1dc6b4a8ac37cf28e37d14cb38beb059d85f7b6c460288
7
+ data.tar.gz: 910c850499f28d49c02fdfca756770a4d182ac7688891efa7cccc920f1dd2180b30fbcb984cf8b34e143d049374cd0d6da947f5f8f55998a89d9183753a17c9b
data/CHANGELOG.md CHANGED
@@ -2,6 +2,39 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.2.1] - 2026-10-11
6
+
7
+ - Update the `zrip` crate dependency to 0.8.11 and `rb-sys` to 0.9.130.
8
+ - Make `FrameCodec` instances Ractor-shareable as documented, with native
9
+ dictionary copies that leave caller strings mutable.
10
+ - Unlock input strings and free native results when Ruby interrupts a call
11
+ that released the GVL.
12
+ - Protect mutable inputs when mutex contention releases the GVL, including
13
+ calls below the normal size threshold.
14
+ - Catch Rust panics inside native callbacks instead of aborting the process.
15
+ - Preserve Ruby exceptions, `Thread#kill`, and `catch`/`throw` through
16
+ protected native calls.
17
+ - Avoid trainer deadlocks during sample coercion and borrow decompression
18
+ input after size coercion.
19
+ - Enforce `max_output_size:` inside the native decoder across concatenated
20
+ frames, before allocating or decoding past the limit.
21
+ - Validate complete frame headers when reading frame content sizes.
22
+ - Correct the README compression level example to the supported maximum.
23
+ - Update GitHub Actions checkout to v7 and check Rust tests, formatting, and
24
+ Clippy in CI.
25
+
26
+ ## [0.2.0] - 2026-08-07
27
+
28
+ - Release the Ruby GVL around large frame/block compression and frame
29
+ decompression calls.
30
+ - Update the `zrip` crate dependency to 0.8.5.
31
+ - Replace Magnus with direct `rb-sys` bindings, add TruffleRuby build support,
32
+ and lower the Ruby requirement to 3.4.
33
+ - Apply `max_output_size:` to the total decompressed output of concatenated
34
+ Zstandard frames.
35
+ - Add RubyDoc metadata and move API reference details from `README.md` into
36
+ YARD comments.
37
+
5
38
  ## [0.1.2] - 2026-08-05
6
39
 
7
40
  - Update `zrip` crate dependency from 0.8.3 to 0.8.4.
data/Cargo.lock CHANGED
@@ -31,9 +31,9 @@ dependencies = [
31
31
 
32
32
  [[package]]
33
33
  name = "bitflags"
34
- version = "2.13.1"
34
+ version = "2.13.2"
35
35
  source = "registry+https://github.com/rust-lang/crates.io-index"
36
- checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
36
+ checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
37
37
 
38
38
  [[package]]
39
39
  name = "cexpr"
@@ -46,9 +46,9 @@ dependencies = [
46
46
 
47
47
  [[package]]
48
48
  name = "cfg-if"
49
- version = "1.0.4"
49
+ version = "1.0.5"
50
50
  source = "registry+https://github.com/rust-lang/crates.io-index"
51
- checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
51
+ checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
52
52
 
53
53
  [[package]]
54
54
  name = "clang-sys"
@@ -63,15 +63,15 @@ dependencies = [
63
63
 
64
64
  [[package]]
65
65
  name = "either"
66
- version = "1.17.0"
66
+ version = "1.19.0"
67
67
  source = "registry+https://github.com/rust-lang/crates.io-index"
68
- checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
68
+ checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be"
69
69
 
70
70
  [[package]]
71
71
  name = "fearless_simd"
72
- version = "0.6.0"
72
+ version = "1.1.0"
73
73
  source = "registry+https://github.com/rust-lang/crates.io-index"
74
- checksum = "e0f5f895dac0865bc235f1364793899569a7db538137f1024dccea56bf41c78d"
74
+ checksum = "3296eb97d869113eaf148a6bdf01884e90b3828ad7ae2340b0f93362fc158611"
75
75
 
76
76
  [[package]]
77
77
  name = "glob"
@@ -90,15 +90,15 @@ dependencies = [
90
90
 
91
91
  [[package]]
92
92
  name = "lazy_static"
93
- version = "1.5.0"
93
+ version = "1.5.1"
94
94
  source = "registry+https://github.com/rust-lang/crates.io-index"
95
- checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
95
+ checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb"
96
96
 
97
97
  [[package]]
98
98
  name = "libc"
99
- version = "0.2.189"
99
+ version = "0.2.190"
100
100
  source = "registry+https://github.com/rust-lang/crates.io-index"
101
- checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
101
+ checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
102
102
 
103
103
  [[package]]
104
104
  name = "libloading"
@@ -110,29 +110,6 @@ dependencies = [
110
110
  "windows-link",
111
111
  ]
112
112
 
113
- [[package]]
114
- name = "magnus"
115
- version = "0.8.2"
116
- source = "registry+https://github.com/rust-lang/crates.io-index"
117
- checksum = "3b36a5b126bbe97eb0d02d07acfeb327036c6319fd816139a49824a83b7f9012"
118
- dependencies = [
119
- "magnus-macros",
120
- "rb-sys",
121
- "rb-sys-env",
122
- "seq-macro",
123
- ]
124
-
125
- [[package]]
126
- name = "magnus-macros"
127
- version = "0.8.0"
128
- source = "registry+https://github.com/rust-lang/crates.io-index"
129
- checksum = "47607461fd8e1513cb4f2076c197d8092d921a1ea75bd08af97398f593751892"
130
- dependencies = [
131
- "proc-macro2",
132
- "quote",
133
- "syn",
134
- ]
135
-
136
113
  [[package]]
137
114
  name = "memchr"
138
115
  version = "2.8.3"
@@ -175,18 +152,18 @@ dependencies = [
175
152
 
176
153
  [[package]]
177
154
  name = "rb-sys"
178
- version = "0.9.128"
155
+ version = "0.9.130"
179
156
  source = "registry+https://github.com/rust-lang/crates.io-index"
180
- checksum = "45ca28513560e56cfb79a62b1fce363c73af170a182024ce880c77ee9429920a"
157
+ checksum = "02faf625bb10ba893e3ae620f19c9fb1b5f8fcae0fe4eb86bb3f2230fad75edb"
181
158
  dependencies = [
182
159
  "rb-sys-build",
183
160
  ]
184
161
 
185
162
  [[package]]
186
163
  name = "rb-sys-build"
187
- version = "0.9.128"
164
+ version = "0.9.130"
188
165
  source = "registry+https://github.com/rust-lang/crates.io-index"
189
- checksum = "ce04b2c55eff3a21aaa623fcc655d94373238e72cac6b3e1a3641ff31649f99a"
166
+ checksum = "05be6f9c86fe5482808162826f6c047d093b3670582296c770de1d94f8066694"
190
167
  dependencies = [
191
168
  "bindgen",
192
169
  "lazy_static",
@@ -197,12 +174,6 @@ dependencies = [
197
174
  "syn",
198
175
  ]
199
176
 
200
- [[package]]
201
- name = "rb-sys-env"
202
- version = "0.2.3"
203
- source = "registry+https://github.com/rust-lang/crates.io-index"
204
- checksum = "cca7ad6a7e21e72151d56fe2495a259b5670e204c3adac41ee7ef676ea08117a"
205
-
206
177
  [[package]]
207
178
  name = "regex"
208
179
  version = "1.13.1"
@@ -238,12 +209,6 @@ version = "2.1.3"
238
209
  source = "registry+https://github.com/rust-lang/crates.io-index"
239
210
  checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
240
211
 
241
- [[package]]
242
- name = "seq-macro"
243
- version = "0.3.6"
244
- source = "registry+https://github.com/rust-lang/crates.io-index"
245
- checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
246
-
247
212
  [[package]]
248
213
  name = "shell-words"
249
214
  version = "1.1.1"
@@ -269,9 +234,9 @@ dependencies = [
269
234
 
270
235
  [[package]]
271
236
  name = "unicode-ident"
272
- version = "1.0.24"
237
+ version = "1.0.26"
273
238
  source = "registry+https://github.com/rust-lang/crates.io-index"
274
- checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
239
+ checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
275
240
 
276
241
  [[package]]
277
242
  name = "windows-link"
@@ -281,18 +246,17 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
281
246
 
282
247
  [[package]]
283
248
  name = "zrip"
284
- version = "0.1.2"
249
+ version = "0.2.1"
285
250
  dependencies = [
286
- "magnus",
287
251
  "rb-sys",
288
- "zrip 0.8.4",
252
+ "zrip 0.8.11",
289
253
  ]
290
254
 
291
255
  [[package]]
292
256
  name = "zrip"
293
- version = "0.8.4"
257
+ version = "0.8.11"
294
258
  source = "registry+https://github.com/rust-lang/crates.io-index"
295
- checksum = "1d6514da35b51d81bfc515782396980ac909fe46925fd19701b36329ddec46e8"
259
+ checksum = "9e85bd0b02784d8753fe5cc435dfb65043be505cb621643a3ac4a0c43eb49e4a"
296
260
  dependencies = [
297
261
  "zrip-core",
298
262
  "zrip-decode",
@@ -301,15 +265,15 @@ dependencies = [
301
265
 
302
266
  [[package]]
303
267
  name = "zrip-core"
304
- version = "0.9.1"
268
+ version = "0.11.0"
305
269
  source = "registry+https://github.com/rust-lang/crates.io-index"
306
- checksum = "9335acd94c1f09f729178fc339f9d49790254c1e98ba076f88df3a3f534c4e7d"
270
+ checksum = "6dec95be8c75252532ba0ef5e738d9da26a6f51ad52cb45f4ed90c89979727c1"
307
271
 
308
272
  [[package]]
309
273
  name = "zrip-decode"
310
- version = "0.8.4"
274
+ version = "0.8.10"
311
275
  source = "registry+https://github.com/rust-lang/crates.io-index"
312
- checksum = "16c26a2ea54a97d013b6f2a430b659fb77e0d5feb0aa3f80cb8c141d6827beba"
276
+ checksum = "aca029cf83b6a6e282008a9aa1079e13f216b28bac670eb1fb0769c1d256cb0e"
313
277
  dependencies = [
314
278
  "fearless_simd",
315
279
  "zrip-core",
@@ -317,9 +281,10 @@ dependencies = [
317
281
 
318
282
  [[package]]
319
283
  name = "zrip-encode"
320
- version = "0.8.4"
284
+ version = "0.9.0"
321
285
  source = "registry+https://github.com/rust-lang/crates.io-index"
322
- checksum = "38e7e22b665b947f0240b44805713e87a15c34e86d0891cbe2856c575c5cda1d"
286
+ checksum = "b657fa83287fe6799596e53540a7b1f179ca34ffd8589d5c576a5b8a1bcc4260"
323
287
  dependencies = [
288
+ "fearless_simd",
324
289
  "zrip-core",
325
290
  ]
data/Cargo.toml CHANGED
@@ -6,4 +6,3 @@ resolver = "2"
6
6
  opt-level = 3
7
7
  lto = true
8
8
  codegen-units = 1
9
- panic = "abort"
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
- # zrip — Ractor-safe Zstandard for Ruby
1
+ # zrip: Ractor-safe Zstandard for Ruby
2
2
 
3
3
  [![CI](https://github.com/paddor/zrip-rb/actions/workflows/ci.yml/badge.svg)](https://github.com/paddor/zrip-rb/actions/workflows/ci.yml)
4
4
  [![Gem Version](https://img.shields.io/gem/v/zrip?color=e9573f)](https://rubygems.org/gems/zrip)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
- [![Ruby](https://img.shields.io/badge/Ruby-%3E%3D%204.0-CC342D?logo=ruby&logoColor=white)](https://www.ruby-lang.org)
6
+ [![Ruby](https://img.shields.io/badge/Ruby-%3E%3D%203.4-CC342D?logo=ruby&logoColor=white)](https://www.ruby-lang.org)
7
7
 
8
8
  Ruby bindings for [zrip](https://crates.io/crates/zrip), a pure-Rust Zstandard
9
- implementation. Built with [magnus](https://github.com/matsadler/magnus) and
10
- declared Ractor-safe so you can compress from any Ractor without a global lock.
9
+ implementation. Built as an `rb-sys` native extension and declared Ractor-safe
10
+ so you can compress from any Ractor without a global lock.
11
11
 
12
12
  ## Features
13
13
 
@@ -22,7 +22,7 @@ declared Ractor-safe so you can compress from any Ractor without a global lock.
22
22
 
23
23
  ## Install
24
24
 
25
- Requires Ruby >= 4.0 and a Rust toolchain (for building the native extension):
25
+ Requires Ruby >= 3.4 and a Rust toolchain (for building the native extension):
26
26
 
27
27
  ```sh
28
28
  gem install zrip
@@ -58,7 +58,7 @@ original = codec.decompress(compressed)
58
58
 
59
59
  ```ruby
60
60
  fast = Zrip::FrameCodec.new(level: -3) # negative = faster
61
- strong = Zrip::FrameCodec.new(level: 19) # higher = smaller output
61
+ strong = Zrip::FrameCodec.new(level: 4) # highest supported level
62
62
  ```
63
63
 
64
64
  ### Bounded decompression
@@ -66,8 +66,8 @@ strong = Zrip::FrameCodec.new(level: 19) # higher = smaller output
66
66
  ```ruby
67
67
  codec = Zrip::FrameCodec.new
68
68
 
69
- # Limit output size to 1 MiB
70
- codec.decompress(compressed, max_output_size: 1_048_576)
69
+ # Limit total output size to 1 MiB
70
+ codec.decompress(compressed, max_output_size: 1024 * 1024)
71
71
 
72
72
  # Read frame content size from header (without decompressing)
73
73
  Zrip::FrameCodec.get_frame_content_size(compressed) #=> 12000
@@ -96,6 +96,9 @@ codec = Zrip::FrameCodec.new(dict: dict)
96
96
 
97
97
  ### Ractor safety
98
98
 
99
+ On Ruby VMs without Ractor support, the codecs still work normally; the
100
+ Ractor-specific guarantees and examples do not apply.
101
+
99
102
  ```ruby
100
103
  codec = Zrip::FrameCodec.new
101
104
 
@@ -111,39 +114,9 @@ end
111
114
  ractors.each { |r| p r.value } # => :ok, :ok, :ok, :ok
112
115
  ```
113
116
 
114
- ## API
115
-
116
- | Class / Module | Method | Description |
117
- |---|---|---|
118
- | `Zrip::FrameCodec` | `.new(dict: nil, level: 1)` | Create a frame codec, optionally with a `Dictionary`, raw `String` dict, or compression level |
119
- | | `.get_frame_content_size(string)` | Read Frame_Content_Size from a Zstd frame header |
120
- | | `#compress(string)` | Compress to Zstd frame |
121
- | | `#decompress(string, max_output_size: nil)` | Decompress a Zstd frame, optionally bounded |
122
- | | `#has_dict?` | Whether a dictionary is loaded |
123
- | | `#id` | Dictionary ID (nil without dict) |
124
- | | `#size` | Dictionary size in bytes (0 without dict) |
125
- | | `#level` | Compression level |
126
- | `Zrip::BlockCodec` | `.new(dict: nil, level: 1)` | Create a block codec, optionally with a dict |
127
- | | `#compress(string)` | Compress to Zstd block |
128
- | | `#decompress(string, max_output_size: nil)` | Decompress a Zstd block, optionally bounded |
129
- | | `#has_dict?` | Whether a dictionary is loaded |
130
- | | `#size` | Dictionary size in bytes (0 without dict) |
131
- | | `#level` | Compression level |
132
- | `Zrip::Dictionary` | `.new(bytes:, id: nil)` | Immutable dictionary value object (`Data.define`) |
133
- | | `#bytes` | Frozen binary dict bytes |
134
- | | `#id` | 32-bit dictionary ID (auto-detected from ZDICT header or SHA-256) |
135
- | | `#size` | Dictionary size in bytes |
136
- | `Zrip::DictTrainer` | `.new(max_dict_size)` | Create a trainer |
137
- | | `#add_sample(string)` | Feed a training sample (skips < 4 bytes) |
138
- | | `#train` | Consume the trainer, return dict bytes |
139
- | | `#sample_count` | Number of accepted samples |
140
- | | `#total_bytes` | Total bytes of accepted samples |
141
- | | `#trained?` | Whether `#train` has been called |
142
- | | `#max_dict_size` | Configured max dict size |
143
- | `Zrip::DecompressError` | | Raised on decompression failure |
144
- | `Zrip::CompressError` | | Raised on compression failure |
145
- | `Zrip::MissingContentSizeError` | | Raised when Frame_Content_Size is absent (subclass of `DecompressError`) |
146
- | `Zrip::OutputSizeLimitError` | | Raised when declared content size exceeds limit (subclass of `DecompressError`) |
117
+ ## Documentation
118
+
119
+ Reference: <https://rubydoc.info/gems/zrip>
147
120
 
148
121
  ## License
149
122
 
data/ext/zrip/Cargo.toml CHANGED
@@ -1,16 +1,16 @@
1
1
  [package]
2
2
  name = "zrip"
3
- version = "0.1.2"
3
+ version = "0.2.1"
4
4
  edition = "2021"
5
+ build = "build.rs"
5
6
 
6
7
  [lib]
7
8
  name = "zrip"
8
9
  crate-type = ["cdylib", "rlib"]
9
10
 
10
11
  [dependencies]
11
- zstd = { version = "0.8.4", package = "zrip", features = ["frame", "dict_builder"] }
12
- magnus = "0.8"
13
- rb-sys = "0.9"
12
+ zstd = { version = "0.8.11", package = "zrip", features = ["frame", "dict_builder"] }
13
+ rb-sys = "0.9.130"
14
14
 
15
15
  [build-dependencies]
16
- rb-sys = "0.9"
16
+ rb-sys = "0.9.130"
data/ext/zrip/build.rs ADDED
@@ -0,0 +1,23 @@
1
+ use std::process::Command;
2
+
3
+ fn main() {
4
+ println!("cargo:rerun-if-env-changed=RUBY");
5
+ println!("cargo:rustc-check-cfg=cfg(ruby_engine, values(\"mri\", \"truffleruby\"))");
6
+
7
+ let ruby = std::env::var("RUBY").unwrap_or_else(|_| "ruby".to_string());
8
+ let output = Command::new(&ruby)
9
+ .arg("-rrbconfig")
10
+ .arg("-e")
11
+ .arg("print RbConfig::CONFIG.fetch('ruby_install_name')")
12
+ .output()
13
+ .unwrap_or_else(|err| panic!("failed to run {ruby}: {err}"));
14
+
15
+ if !output.status.success() {
16
+ panic!("failed to query Ruby engine with {ruby}");
17
+ }
18
+
19
+ match String::from_utf8_lossy(&output.stdout).trim() {
20
+ "truffleruby" => println!("cargo:rustc-cfg=ruby_engine=\"truffleruby\""),
21
+ _ => println!("cargo:rustc-cfg=ruby_engine=\"mri\""),
22
+ }
23
+ }