lz4_flex 0.1.1.pre2
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 +7 -0
- data/Cargo.lock +510 -0
- data/Cargo.toml +12 -0
- data/LICENSE.md +21 -0
- data/README.md +99 -0
- data/ext/lz4_flex_ext/Cargo.toml +18 -0
- data/ext/lz4_flex_ext/extconf.rb +7 -0
- data/ext/lz4_flex_ext/src/block.rs +81 -0
- data/ext/lz4_flex_ext/src/header.rs +118 -0
- data/ext/lz4_flex_ext/src/helpers.rs +213 -0
- data/ext/lz4_flex_ext/src/lib.rs +71 -0
- data/lib/lz4_flex/version.rb +6 -0
- data/lib/lz4_flex.rb +10 -0
- metadata +77 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: cb58450d76e8b265b117c1760b74dce5286451dc5fc99c20d66c33c763fbace1
|
|
4
|
+
data.tar.gz: 993a74df952364f4773f4afeeea9763e5f690c3b98a26e7914e5e2a20c9d4de4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 2f750064cd574bf2d7220aecc37b21d5413aa0d1dbeef15038be2831798966287215613717db0e645b17f48fa80be8baa3b08021870b70e8326ff22cf95a574c
|
|
7
|
+
data.tar.gz: 718b5b9b0cf4f47a1b333c78e4c38e9ea680ca22333e146408e7aa5aeefab4f340a3915cd9302e2fb34c59e3ca137234160b780fc7ea4f8b4869670533504ae6
|
data/Cargo.lock
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 3
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "aho-corasick"
|
|
7
|
+
version = "1.1.3"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"memchr",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "atomic-polyfill"
|
|
16
|
+
version = "1.0.3"
|
|
17
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
+
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"critical-section",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "autocfg"
|
|
25
|
+
version = "1.3.0"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
|
28
|
+
|
|
29
|
+
[[package]]
|
|
30
|
+
name = "bindgen"
|
|
31
|
+
version = "0.69.4"
|
|
32
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
33
|
+
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
|
|
34
|
+
dependencies = [
|
|
35
|
+
"bitflags",
|
|
36
|
+
"cexpr",
|
|
37
|
+
"clang-sys",
|
|
38
|
+
"itertools",
|
|
39
|
+
"lazy_static",
|
|
40
|
+
"lazycell",
|
|
41
|
+
"proc-macro2",
|
|
42
|
+
"quote",
|
|
43
|
+
"regex",
|
|
44
|
+
"rustc-hash",
|
|
45
|
+
"shlex",
|
|
46
|
+
"syn",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[[package]]
|
|
50
|
+
name = "bitflags"
|
|
51
|
+
version = "2.6.0"
|
|
52
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
53
|
+
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
|
54
|
+
|
|
55
|
+
[[package]]
|
|
56
|
+
name = "byteorder"
|
|
57
|
+
version = "1.5.0"
|
|
58
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
59
|
+
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
60
|
+
|
|
61
|
+
[[package]]
|
|
62
|
+
name = "cexpr"
|
|
63
|
+
version = "0.6.0"
|
|
64
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
65
|
+
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
|
66
|
+
dependencies = [
|
|
67
|
+
"nom",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[[package]]
|
|
71
|
+
name = "cfg-if"
|
|
72
|
+
version = "1.0.0"
|
|
73
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
74
|
+
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
75
|
+
|
|
76
|
+
[[package]]
|
|
77
|
+
name = "clang-sys"
|
|
78
|
+
version = "1.8.1"
|
|
79
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
80
|
+
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
|
81
|
+
dependencies = [
|
|
82
|
+
"glob",
|
|
83
|
+
"libc",
|
|
84
|
+
"libloading",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
[[package]]
|
|
88
|
+
name = "cobs"
|
|
89
|
+
version = "0.2.3"
|
|
90
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
91
|
+
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
|
|
92
|
+
|
|
93
|
+
[[package]]
|
|
94
|
+
name = "critical-section"
|
|
95
|
+
version = "1.1.2"
|
|
96
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
97
|
+
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
|
98
|
+
|
|
99
|
+
[[package]]
|
|
100
|
+
name = "either"
|
|
101
|
+
version = "1.13.0"
|
|
102
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
103
|
+
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
|
104
|
+
|
|
105
|
+
[[package]]
|
|
106
|
+
name = "glob"
|
|
107
|
+
version = "0.3.1"
|
|
108
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
109
|
+
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
|
110
|
+
|
|
111
|
+
[[package]]
|
|
112
|
+
name = "hash32"
|
|
113
|
+
version = "0.2.1"
|
|
114
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
115
|
+
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
|
116
|
+
dependencies = [
|
|
117
|
+
"byteorder",
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[[package]]
|
|
121
|
+
name = "heapless"
|
|
122
|
+
version = "0.7.17"
|
|
123
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
124
|
+
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
|
125
|
+
dependencies = [
|
|
126
|
+
"atomic-polyfill",
|
|
127
|
+
"hash32",
|
|
128
|
+
"rustc_version",
|
|
129
|
+
"serde",
|
|
130
|
+
"spin",
|
|
131
|
+
"stable_deref_trait",
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
[[package]]
|
|
135
|
+
name = "itertools"
|
|
136
|
+
version = "0.12.1"
|
|
137
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
138
|
+
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
|
139
|
+
dependencies = [
|
|
140
|
+
"either",
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
[[package]]
|
|
144
|
+
name = "lazy_static"
|
|
145
|
+
version = "1.5.0"
|
|
146
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
147
|
+
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
148
|
+
|
|
149
|
+
[[package]]
|
|
150
|
+
name = "lazycell"
|
|
151
|
+
version = "1.3.0"
|
|
152
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
153
|
+
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
154
|
+
|
|
155
|
+
[[package]]
|
|
156
|
+
name = "libc"
|
|
157
|
+
version = "0.2.155"
|
|
158
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
|
+
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
|
160
|
+
|
|
161
|
+
[[package]]
|
|
162
|
+
name = "libloading"
|
|
163
|
+
version = "0.8.5"
|
|
164
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
165
|
+
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
|
166
|
+
dependencies = [
|
|
167
|
+
"cfg-if",
|
|
168
|
+
"windows-targets",
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
[[package]]
|
|
172
|
+
name = "lock_api"
|
|
173
|
+
version = "0.4.12"
|
|
174
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
175
|
+
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
|
176
|
+
dependencies = [
|
|
177
|
+
"autocfg",
|
|
178
|
+
"scopeguard",
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
[[package]]
|
|
182
|
+
name = "lz4_flex"
|
|
183
|
+
version = "0.11.3"
|
|
184
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
185
|
+
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
|
|
186
|
+
dependencies = [
|
|
187
|
+
"twox-hash",
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
[[package]]
|
|
191
|
+
name = "lz4_flex_ext"
|
|
192
|
+
version = "0.1.0"
|
|
193
|
+
dependencies = [
|
|
194
|
+
"lz4_flex",
|
|
195
|
+
"magnus",
|
|
196
|
+
"postcard",
|
|
197
|
+
"rb-sys",
|
|
198
|
+
"serde",
|
|
199
|
+
"static_assertions",
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
[[package]]
|
|
203
|
+
name = "magnus"
|
|
204
|
+
version = "0.7.1"
|
|
205
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
206
|
+
checksum = "3d87ae53030f3a22e83879e666cb94e58a7bdf31706878a0ba48752994146dab"
|
|
207
|
+
dependencies = [
|
|
208
|
+
"magnus-macros",
|
|
209
|
+
"rb-sys",
|
|
210
|
+
"rb-sys-env",
|
|
211
|
+
"seq-macro",
|
|
212
|
+
]
|
|
213
|
+
|
|
214
|
+
[[package]]
|
|
215
|
+
name = "magnus-macros"
|
|
216
|
+
version = "0.6.0"
|
|
217
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
218
|
+
checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3"
|
|
219
|
+
dependencies = [
|
|
220
|
+
"proc-macro2",
|
|
221
|
+
"quote",
|
|
222
|
+
"syn",
|
|
223
|
+
]
|
|
224
|
+
|
|
225
|
+
[[package]]
|
|
226
|
+
name = "memchr"
|
|
227
|
+
version = "2.7.4"
|
|
228
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
229
|
+
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
|
230
|
+
|
|
231
|
+
[[package]]
|
|
232
|
+
name = "minimal-lexical"
|
|
233
|
+
version = "0.2.1"
|
|
234
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
235
|
+
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
236
|
+
|
|
237
|
+
[[package]]
|
|
238
|
+
name = "nom"
|
|
239
|
+
version = "7.1.3"
|
|
240
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
241
|
+
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
|
242
|
+
dependencies = [
|
|
243
|
+
"memchr",
|
|
244
|
+
"minimal-lexical",
|
|
245
|
+
]
|
|
246
|
+
|
|
247
|
+
[[package]]
|
|
248
|
+
name = "postcard"
|
|
249
|
+
version = "1.0.8"
|
|
250
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
251
|
+
checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8"
|
|
252
|
+
dependencies = [
|
|
253
|
+
"cobs",
|
|
254
|
+
"heapless",
|
|
255
|
+
"serde",
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
[[package]]
|
|
259
|
+
name = "proc-macro2"
|
|
260
|
+
version = "1.0.86"
|
|
261
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
262
|
+
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
|
263
|
+
dependencies = [
|
|
264
|
+
"unicode-ident",
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
[[package]]
|
|
268
|
+
name = "quote"
|
|
269
|
+
version = "1.0.36"
|
|
270
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
271
|
+
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
|
272
|
+
dependencies = [
|
|
273
|
+
"proc-macro2",
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
[[package]]
|
|
277
|
+
name = "rb-sys"
|
|
278
|
+
version = "0.9.101"
|
|
279
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
280
|
+
checksum = "1ba2704ccfa7875c91792c57a9aa7c3caac524d3036c122e36eeddad6f6e7c6f"
|
|
281
|
+
dependencies = [
|
|
282
|
+
"rb-sys-build",
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
[[package]]
|
|
286
|
+
name = "rb-sys-build"
|
|
287
|
+
version = "0.9.101"
|
|
288
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
289
|
+
checksum = "c73585ec80c217b7a81257ca9bb89b191b5e452ec4b9106dc4c2e4e96a822242"
|
|
290
|
+
dependencies = [
|
|
291
|
+
"bindgen",
|
|
292
|
+
"lazy_static",
|
|
293
|
+
"proc-macro2",
|
|
294
|
+
"quote",
|
|
295
|
+
"regex",
|
|
296
|
+
"shell-words",
|
|
297
|
+
"syn",
|
|
298
|
+
]
|
|
299
|
+
|
|
300
|
+
[[package]]
|
|
301
|
+
name = "rb-sys-env"
|
|
302
|
+
version = "0.1.2"
|
|
303
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
304
|
+
checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb"
|
|
305
|
+
|
|
306
|
+
[[package]]
|
|
307
|
+
name = "regex"
|
|
308
|
+
version = "1.10.6"
|
|
309
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
310
|
+
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
|
311
|
+
dependencies = [
|
|
312
|
+
"aho-corasick",
|
|
313
|
+
"memchr",
|
|
314
|
+
"regex-automata",
|
|
315
|
+
"regex-syntax",
|
|
316
|
+
]
|
|
317
|
+
|
|
318
|
+
[[package]]
|
|
319
|
+
name = "regex-automata"
|
|
320
|
+
version = "0.4.7"
|
|
321
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
322
|
+
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
|
323
|
+
dependencies = [
|
|
324
|
+
"aho-corasick",
|
|
325
|
+
"memchr",
|
|
326
|
+
"regex-syntax",
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
[[package]]
|
|
330
|
+
name = "regex-syntax"
|
|
331
|
+
version = "0.8.4"
|
|
332
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
333
|
+
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
|
334
|
+
|
|
335
|
+
[[package]]
|
|
336
|
+
name = "rustc-hash"
|
|
337
|
+
version = "1.1.0"
|
|
338
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
339
|
+
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|
340
|
+
|
|
341
|
+
[[package]]
|
|
342
|
+
name = "rustc_version"
|
|
343
|
+
version = "0.4.0"
|
|
344
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
345
|
+
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
|
346
|
+
dependencies = [
|
|
347
|
+
"semver",
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
[[package]]
|
|
351
|
+
name = "scopeguard"
|
|
352
|
+
version = "1.2.0"
|
|
353
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
354
|
+
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
355
|
+
|
|
356
|
+
[[package]]
|
|
357
|
+
name = "semver"
|
|
358
|
+
version = "1.0.23"
|
|
359
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
360
|
+
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
|
361
|
+
|
|
362
|
+
[[package]]
|
|
363
|
+
name = "seq-macro"
|
|
364
|
+
version = "0.3.5"
|
|
365
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
366
|
+
checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
|
|
367
|
+
|
|
368
|
+
[[package]]
|
|
369
|
+
name = "serde"
|
|
370
|
+
version = "1.0.208"
|
|
371
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
372
|
+
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
|
|
373
|
+
dependencies = [
|
|
374
|
+
"serde_derive",
|
|
375
|
+
]
|
|
376
|
+
|
|
377
|
+
[[package]]
|
|
378
|
+
name = "serde_derive"
|
|
379
|
+
version = "1.0.208"
|
|
380
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
381
|
+
checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
|
|
382
|
+
dependencies = [
|
|
383
|
+
"proc-macro2",
|
|
384
|
+
"quote",
|
|
385
|
+
"syn",
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
[[package]]
|
|
389
|
+
name = "shell-words"
|
|
390
|
+
version = "1.1.0"
|
|
391
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
392
|
+
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
|
393
|
+
|
|
394
|
+
[[package]]
|
|
395
|
+
name = "shlex"
|
|
396
|
+
version = "1.3.0"
|
|
397
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
398
|
+
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
399
|
+
|
|
400
|
+
[[package]]
|
|
401
|
+
name = "spin"
|
|
402
|
+
version = "0.9.8"
|
|
403
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
404
|
+
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
|
405
|
+
dependencies = [
|
|
406
|
+
"lock_api",
|
|
407
|
+
]
|
|
408
|
+
|
|
409
|
+
[[package]]
|
|
410
|
+
name = "stable_deref_trait"
|
|
411
|
+
version = "1.2.0"
|
|
412
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
413
|
+
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|
414
|
+
|
|
415
|
+
[[package]]
|
|
416
|
+
name = "static_assertions"
|
|
417
|
+
version = "1.1.0"
|
|
418
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
419
|
+
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|
420
|
+
|
|
421
|
+
[[package]]
|
|
422
|
+
name = "syn"
|
|
423
|
+
version = "2.0.74"
|
|
424
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
425
|
+
checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7"
|
|
426
|
+
dependencies = [
|
|
427
|
+
"proc-macro2",
|
|
428
|
+
"quote",
|
|
429
|
+
"unicode-ident",
|
|
430
|
+
]
|
|
431
|
+
|
|
432
|
+
[[package]]
|
|
433
|
+
name = "twox-hash"
|
|
434
|
+
version = "1.6.3"
|
|
435
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
436
|
+
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
|
437
|
+
dependencies = [
|
|
438
|
+
"cfg-if",
|
|
439
|
+
"static_assertions",
|
|
440
|
+
]
|
|
441
|
+
|
|
442
|
+
[[package]]
|
|
443
|
+
name = "unicode-ident"
|
|
444
|
+
version = "1.0.12"
|
|
445
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
446
|
+
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
|
447
|
+
|
|
448
|
+
[[package]]
|
|
449
|
+
name = "windows-targets"
|
|
450
|
+
version = "0.52.6"
|
|
451
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
452
|
+
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
|
453
|
+
dependencies = [
|
|
454
|
+
"windows_aarch64_gnullvm",
|
|
455
|
+
"windows_aarch64_msvc",
|
|
456
|
+
"windows_i686_gnu",
|
|
457
|
+
"windows_i686_gnullvm",
|
|
458
|
+
"windows_i686_msvc",
|
|
459
|
+
"windows_x86_64_gnu",
|
|
460
|
+
"windows_x86_64_gnullvm",
|
|
461
|
+
"windows_x86_64_msvc",
|
|
462
|
+
]
|
|
463
|
+
|
|
464
|
+
[[package]]
|
|
465
|
+
name = "windows_aarch64_gnullvm"
|
|
466
|
+
version = "0.52.6"
|
|
467
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
468
|
+
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
|
469
|
+
|
|
470
|
+
[[package]]
|
|
471
|
+
name = "windows_aarch64_msvc"
|
|
472
|
+
version = "0.52.6"
|
|
473
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
474
|
+
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
|
475
|
+
|
|
476
|
+
[[package]]
|
|
477
|
+
name = "windows_i686_gnu"
|
|
478
|
+
version = "0.52.6"
|
|
479
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
480
|
+
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
|
481
|
+
|
|
482
|
+
[[package]]
|
|
483
|
+
name = "windows_i686_gnullvm"
|
|
484
|
+
version = "0.52.6"
|
|
485
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
486
|
+
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
|
487
|
+
|
|
488
|
+
[[package]]
|
|
489
|
+
name = "windows_i686_msvc"
|
|
490
|
+
version = "0.52.6"
|
|
491
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
492
|
+
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
|
493
|
+
|
|
494
|
+
[[package]]
|
|
495
|
+
name = "windows_x86_64_gnu"
|
|
496
|
+
version = "0.52.6"
|
|
497
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
498
|
+
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
|
499
|
+
|
|
500
|
+
[[package]]
|
|
501
|
+
name = "windows_x86_64_gnullvm"
|
|
502
|
+
version = "0.52.6"
|
|
503
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
504
|
+
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
|
505
|
+
|
|
506
|
+
[[package]]
|
|
507
|
+
name = "windows_x86_64_msvc"
|
|
508
|
+
version = "0.52.6"
|
|
509
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
510
|
+
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
data/Cargo.toml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# This Cargo.toml is here to let externals tools (IDEs, etc.) know that this is
|
|
2
|
+
# a Rust project. Your extensions dependencies should be added to the Cargo.toml
|
|
3
|
+
# in the ext/ directory.
|
|
4
|
+
|
|
5
|
+
[workspace]
|
|
6
|
+
members = ["./ext/lz4_flex_ext"]
|
|
7
|
+
resolver = "2"
|
|
8
|
+
|
|
9
|
+
[profile.release]
|
|
10
|
+
debug = true
|
|
11
|
+
codegen-units = 1
|
|
12
|
+
lto = "fat"
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Shopify
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# `lz4-flex-rb`
|
|
2
|
+
|
|
3
|
+
## About this library
|
|
4
|
+
|
|
5
|
+
**Introduction:**
|
|
6
|
+
`lz4-flex-rb` is a modern LZ4 compression library for Ruby, leveraging the
|
|
7
|
+
power of the [`lz4_flex`](https://github.com/PSeitz/lz4_flex) Rust crate. This
|
|
8
|
+
library provides a pure Rust implementation of the LZ4 algorithm, ensuring high
|
|
9
|
+
performance and safety. One of the standout features of `lz4_flex-rb` is its
|
|
10
|
+
ability to conditionally unlock the Global VM Lock (GVL) for threaded web
|
|
11
|
+
servers, enhancing concurrency and performance in multi-threaded environments.
|
|
12
|
+
|
|
13
|
+
## How to install this library
|
|
14
|
+
|
|
15
|
+
### Requirements
|
|
16
|
+
- Ruby 3.0 or higher
|
|
17
|
+
- Rust (for building the native extension)
|
|
18
|
+
|
|
19
|
+
### Setup
|
|
20
|
+
Add this line to your application's Gemfile:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
gem 'lz4_flex'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
And then execute:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
bundle install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Troubleshooting
|
|
33
|
+
|
|
34
|
+
If you encounter issues during installation, ensure that Rust is correctly installed and available in your PATH. You can install Rust from [rustup.rs](https://rustup.rs/).
|
|
35
|
+
|
|
36
|
+
## How to use this library
|
|
37
|
+
|
|
38
|
+
There are two methods provided, `LZ4Flex.compress` and `Lz4Flex.decompress`.
|
|
39
|
+
Both of these methods utilize the lz4 block format, with a small header to
|
|
40
|
+
record the string's size and encoding.
|
|
41
|
+
|
|
42
|
+
### Basic Usage
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
require 'lz4_flex'
|
|
46
|
+
|
|
47
|
+
# Compress data
|
|
48
|
+
compressed = LZ4Flex.compress("Hello, World!")
|
|
49
|
+
|
|
50
|
+
# Decompress data
|
|
51
|
+
decompressed = LZ4Flex.decompress(compressed)
|
|
52
|
+
|
|
53
|
+
puts decompressed # => "Hello, World!"
|
|
54
|
+
puts decompressed.encoding # => Encoding::UTF_8
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The header used in these methods will not be recognizable from other lz4 block
|
|
58
|
+
parsers. If you need that, it's best to use the Frame API (which is currently a
|
|
59
|
+
WIP).
|
|
60
|
+
|
|
61
|
+
### Migrating from `lz4-ruby`
|
|
62
|
+
|
|
63
|
+
The [`lz4-ruby`](https://github.com/komiya-atsushi/lz4-ruby) gem uses a slighty
|
|
64
|
+
different header format, which keeps track of string size but not the string's
|
|
65
|
+
encoding.
|
|
66
|
+
|
|
67
|
+
To make it easy to migrate to `lz4_flex`, we provide a parser for the
|
|
68
|
+
`lz4-ruby` format:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
# Say you have a string that was compressed with lz4-ruby...
|
|
72
|
+
lz4_ruby_compressed = LZ4.compress("Yo!")
|
|
73
|
+
|
|
74
|
+
# You can decode it with lz4_flex:
|
|
75
|
+
decompressed = Lz4Flex::VarInt.decompress(lz4_ruby_compressed)
|
|
76
|
+
|
|
77
|
+
puts decompressed #=> "Yo!"
|
|
78
|
+
puts decompressed.encoding #=> Encoding::BINARY
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Combine
|
|
82
|
+
|
|
83
|
+
### Running Tests
|
|
84
|
+
To run the tests, execute:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
bundle exec rake
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Contribute to this library (optional)
|
|
91
|
+
|
|
92
|
+
1. Fork the repository.
|
|
93
|
+
2. Create a new branch (`git checkout -b my-feature-branch`).
|
|
94
|
+
3. Make your changes.
|
|
95
|
+
4. Commit your changes (`git commit -am 'Add new feature'`).
|
|
96
|
+
5. Push to the branch (`git push origin my-feature-branch`).
|
|
97
|
+
6. Create a new Pull Request.
|
|
98
|
+
|
|
99
|
+
Please ensure your code adheres to the project's coding standards and includes appropriate tests.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "lz4_flex_ext"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
authors = ["Ian Ker-Seymer <ian.kerseymer@shopify.com>"]
|
|
6
|
+
license = "MIT"
|
|
7
|
+
publish = false
|
|
8
|
+
|
|
9
|
+
[lib]
|
|
10
|
+
crate-type = ["cdylib"]
|
|
11
|
+
|
|
12
|
+
[dependencies]
|
|
13
|
+
lz4_flex = { version = "0.11.3", default-features = true }
|
|
14
|
+
magnus = { version = "0.7.1", features = ["rb-sys"] }
|
|
15
|
+
postcard = "1.0.8"
|
|
16
|
+
rb-sys = { version = "0.9.101", features = ["stable-api-compiled-fallback"] }
|
|
17
|
+
serde = { version = "1.0.208", features = ["derive"] }
|
|
18
|
+
static_assertions = "1.1.0"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
use lz4_flex::block::{compress_into, decompress_into, get_maximum_output_size};
|
|
2
|
+
|
|
3
|
+
use crate::Header;
|
|
4
|
+
use crate::LockedRString;
|
|
5
|
+
use crate::{decode_error_class, encode_error_class, helpers::*};
|
|
6
|
+
|
|
7
|
+
use magnus::{prelude::*, Error, RString};
|
|
8
|
+
|
|
9
|
+
static_assertions::assert_eq_size!(Header, [u8; 8]);
|
|
10
|
+
|
|
11
|
+
pub(crate) fn compress_with_header(
|
|
12
|
+
header: &Header,
|
|
13
|
+
input: LockedRString,
|
|
14
|
+
varint: bool,
|
|
15
|
+
) -> Result<RString, Error> {
|
|
16
|
+
let bufsize = get_maximum_output_size(input.len()) + Header::MAX_SERIALIZED_SIZE;
|
|
17
|
+
let mut output = RStringMut::buf_new(bufsize);
|
|
18
|
+
output.expand(bufsize);
|
|
19
|
+
|
|
20
|
+
let outbuf = output.as_mut_slice();
|
|
21
|
+
|
|
22
|
+
let (header_len, outbuf) = if varint {
|
|
23
|
+
header.write_varint_to(outbuf)
|
|
24
|
+
} else {
|
|
25
|
+
header.write_to(outbuf)
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
let outsize = nogvl_if_large(output.capacity(), || {
|
|
29
|
+
compress_into(input.as_slice(), outbuf)
|
|
30
|
+
})
|
|
31
|
+
.map_err(|e| Error::new(encode_error_class(), e.to_string()))?;
|
|
32
|
+
|
|
33
|
+
output.set_len(outsize + header_len);
|
|
34
|
+
Ok(output.into_inner())
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Encodes a block of data using LZ4 compression, with encoding awareness of the string.
|
|
38
|
+
pub(crate) fn compress(input: LockedRString) -> Result<RString, Error> {
|
|
39
|
+
let header = Header::new(input.len() as u32, input.encoding()?);
|
|
40
|
+
|
|
41
|
+
compress_with_header(&header, input, false)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
pub(crate) fn compress_varint(input: LockedRString) -> Result<RString, Error> {
|
|
45
|
+
let header = Header::new(input.len() as u32, Encoding::Binary);
|
|
46
|
+
|
|
47
|
+
compress_with_header(&header, input, true)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pub(crate) fn decompress_with_header(
|
|
51
|
+
header: &Header,
|
|
52
|
+
input_slice: &[u8],
|
|
53
|
+
) -> Result<RString, Error> {
|
|
54
|
+
let mut output = RStringMut::buf_new(header.size as usize);
|
|
55
|
+
output.expand(header.size as usize);
|
|
56
|
+
|
|
57
|
+
nogvl_if_large(output.capacity(), || {
|
|
58
|
+
decompress_into(input_slice, output.as_mut_slice())
|
|
59
|
+
})
|
|
60
|
+
.map_err(|e| Error::new(decode_error_class(), e.to_string()))?;
|
|
61
|
+
|
|
62
|
+
output.set_len(header.size as usize);
|
|
63
|
+
let output = output.into_inner();
|
|
64
|
+
output.enc_set(header.encoding().encindex())?;
|
|
65
|
+
|
|
66
|
+
Ok(output)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
pub(crate) fn decompress(input: LockedRString) -> Result<RString, Error> {
|
|
70
|
+
let input_slice = input.as_slice();
|
|
71
|
+
let (header, input_slice) = Header::from_bytes(input_slice)?;
|
|
72
|
+
|
|
73
|
+
decompress_with_header(&header, input_slice)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
pub(crate) fn decompress_varint(input: LockedRString) -> Result<RString, Error> {
|
|
77
|
+
let input_slice = input.as_slice();
|
|
78
|
+
let (header, input_slice) = Header::from_varint(input_slice)?;
|
|
79
|
+
|
|
80
|
+
decompress_with_header(&header, input_slice)
|
|
81
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
use magnus::Error;
|
|
2
|
+
use serde::{Deserialize, Serialize};
|
|
3
|
+
|
|
4
|
+
use crate::{base_error_class, decode_error_class, Encoding};
|
|
5
|
+
|
|
6
|
+
#[derive(Debug, Serialize, Deserialize)]
|
|
7
|
+
#[repr(transparent)]
|
|
8
|
+
pub(crate) struct VersionAndEncoding(u8);
|
|
9
|
+
|
|
10
|
+
impl VersionAndEncoding {
|
|
11
|
+
const fn new(version: u8, encoding: Encoding) -> Self {
|
|
12
|
+
Self((version << 4) | encoding as u8)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const fn version(&self) -> u8 {
|
|
16
|
+
self.0 >> 4
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const fn encoding(&self) -> Encoding {
|
|
20
|
+
Encoding::from_u8(self.0 & 0b1111)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#[derive(Debug, Serialize, Deserialize)]
|
|
25
|
+
#[repr(C)]
|
|
26
|
+
pub(crate) struct Header {
|
|
27
|
+
pub(crate) metadata: VersionAndEncoding,
|
|
28
|
+
pub(crate) size: u32,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
impl Header {
|
|
32
|
+
pub(crate) const MAX_SERIALIZED_SIZE: usize = size_of::<Self>();
|
|
33
|
+
|
|
34
|
+
pub(crate) fn from_varint(bytes: &[u8]) -> Result<(Self, &[u8]), Error> {
|
|
35
|
+
let mut val = 0u32;
|
|
36
|
+
let mut varbyte_len = 0;
|
|
37
|
+
|
|
38
|
+
for &b in bytes.iter() {
|
|
39
|
+
val |= ((b & 0x7F) as u32) << (7 * varbyte_len);
|
|
40
|
+
varbyte_len += 1;
|
|
41
|
+
|
|
42
|
+
if b & 0x80 == 0 {
|
|
43
|
+
let header = Self {
|
|
44
|
+
metadata: VersionAndEncoding::new(0, Encoding::Binary),
|
|
45
|
+
size: val,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return Ok((header, &bytes[varbyte_len..]));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if varbyte_len > 5 {
|
|
52
|
+
return Err(Error::new(decode_error_class(), "varint too long"));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Err(Error::new(decode_error_class(), "unexpected end of varint"))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
pub(crate) fn new(size: u32, encoding: Encoding) -> Self {
|
|
60
|
+
Self {
|
|
61
|
+
metadata: VersionAndEncoding::new(1, encoding),
|
|
62
|
+
size,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
pub(crate) const fn encoding(&self) -> Encoding {
|
|
67
|
+
self.metadata.encoding()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
pub(crate) fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error> {
|
|
71
|
+
let (header, rest) = postcard::take_from_bytes::<Self>(bytes).map_err(|e| {
|
|
72
|
+
Error::new(
|
|
73
|
+
decode_error_class(),
|
|
74
|
+
format!("failed to deserialize header: {}", e),
|
|
75
|
+
)
|
|
76
|
+
})?;
|
|
77
|
+
|
|
78
|
+
if header.metadata.version() != 1 {
|
|
79
|
+
return Err(Error::new(
|
|
80
|
+
base_error_class(),
|
|
81
|
+
format!("invalid header version: {}", header.metadata.version()),
|
|
82
|
+
));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Ok((header, rest))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
pub(crate) fn write_to<'a>(&self, buf: &'a mut [u8]) -> (usize, &'a mut [u8]) {
|
|
89
|
+
let serialized_slice_len = {
|
|
90
|
+
postcard::to_slice(self, buf)
|
|
91
|
+
.expect("failed to serialize header")
|
|
92
|
+
.len()
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
(serialized_slice_len, &mut buf[serialized_slice_len..])
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
pub(crate) fn write_varint_to<'a>(&self, buf: &'a mut [u8]) -> (usize, &'a mut [u8]) {
|
|
99
|
+
let mut val = self.size;
|
|
100
|
+
let mut index = 0;
|
|
101
|
+
|
|
102
|
+
loop {
|
|
103
|
+
let byte = (val & 0x7f) as u8;
|
|
104
|
+
val >>= 7;
|
|
105
|
+
|
|
106
|
+
if val == 0 {
|
|
107
|
+
buf[index] = byte;
|
|
108
|
+
index += 1;
|
|
109
|
+
break;
|
|
110
|
+
} else {
|
|
111
|
+
buf[index] = byte | 0x80;
|
|
112
|
+
index += 1;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
(index, &mut buf[index..])
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
use serde::{Deserialize, Serialize};
|
|
2
|
+
use std::{cell::Cell, ffi::c_void, marker::PhantomData, mem::MaybeUninit, ptr::null_mut};
|
|
3
|
+
|
|
4
|
+
use magnus::{
|
|
5
|
+
encoding::{EncodingCapable, Index},
|
|
6
|
+
exception::type_error,
|
|
7
|
+
rb_sys::AsRawValue,
|
|
8
|
+
value::ReprValue,
|
|
9
|
+
Error, RString, Ruby, TryConvert, Value,
|
|
10
|
+
};
|
|
11
|
+
use rb_sys::{
|
|
12
|
+
rb_gc_guard, rb_str_locktmp, rb_str_modify_expand, rb_str_set_len, rb_str_unlocktmp,
|
|
13
|
+
rb_thread_call_without_gvl, RSTRING_PTR,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
use crate::base_error_class;
|
|
17
|
+
|
|
18
|
+
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
19
|
+
#[repr(u8)]
|
|
20
|
+
pub(crate) enum Encoding {
|
|
21
|
+
Utf8 = 0,
|
|
22
|
+
Binary = 1,
|
|
23
|
+
UsAscii = 2,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
impl Encoding {
|
|
27
|
+
pub(crate) fn encindex(self) -> Index {
|
|
28
|
+
let ruby = unsafe { Ruby::get_unchecked() };
|
|
29
|
+
|
|
30
|
+
match self {
|
|
31
|
+
Self::Utf8 => ruby.utf8_encindex(),
|
|
32
|
+
Self::Binary => ruby.ascii8bit_encindex(),
|
|
33
|
+
Self::UsAscii => ruby.usascii_encindex(),
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
pub(crate) const fn from_u8(value: u8) -> Self {
|
|
38
|
+
match value {
|
|
39
|
+
0 => Self::Utf8,
|
|
40
|
+
1 => Self::Binary,
|
|
41
|
+
2 => Self::UsAscii,
|
|
42
|
+
_ => unreachable!(),
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
impl TryFrom<RString> for Encoding {
|
|
48
|
+
type Error = Error;
|
|
49
|
+
|
|
50
|
+
fn try_from(string: RString) -> Result<Self, Self::Error> {
|
|
51
|
+
let ruby = unsafe { Ruby::get_unchecked() };
|
|
52
|
+
|
|
53
|
+
let enc = string.enc_get();
|
|
54
|
+
|
|
55
|
+
if enc == ruby.utf8_encindex() {
|
|
56
|
+
return Ok(Encoding::Utf8);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if enc == ruby.ascii8bit_encindex() {
|
|
60
|
+
return Ok(Encoding::Binary);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if enc == ruby.usascii_encindex() {
|
|
64
|
+
return Ok(Encoding::UsAscii);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Err(Error::new(
|
|
68
|
+
base_error_class(),
|
|
69
|
+
"unsupported encoding for string, please use Lz4Flex.compress_block instead".to_owned(),
|
|
70
|
+
))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#[derive(Debug)]
|
|
75
|
+
pub struct LockedRString<'a>(pub(crate) RString, PhantomData<&'a ()>);
|
|
76
|
+
|
|
77
|
+
impl<'a> LockedRString<'a> {
|
|
78
|
+
pub(crate) fn new(string: RString) -> Self {
|
|
79
|
+
unsafe { rb_str_locktmp(string.as_raw()) };
|
|
80
|
+
|
|
81
|
+
Self(string, PhantomData)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
pub(crate) fn as_slice(&self) -> &'a [u8] {
|
|
85
|
+
unsafe {
|
|
86
|
+
std::slice::from_raw_parts(RSTRING_PTR(self.0.as_raw()) as *const u8, self.0.len())
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
pub(crate) fn len(&self) -> usize {
|
|
91
|
+
self.0.len()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
pub(crate) fn encoding(&self) -> Result<Encoding, Error> {
|
|
95
|
+
Encoding::try_from(self.0)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
impl Drop for LockedRString<'_> {
|
|
100
|
+
fn drop(&mut self) {
|
|
101
|
+
unsafe { rb_str_unlocktmp(self.0.as_raw()) };
|
|
102
|
+
// Keep the value alive while we hold this RString
|
|
103
|
+
let _ = rb_gc_guard!(self.0.as_raw());
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
impl TryConvert for LockedRString<'_> {
|
|
108
|
+
fn try_convert(val: Value) -> Result<Self, magnus::Error> {
|
|
109
|
+
let rstring: RString = RString::from_value(val).ok_or(magnus::Error::new(
|
|
110
|
+
type_error(),
|
|
111
|
+
format!("expected String, got {}", val.class()),
|
|
112
|
+
))?;
|
|
113
|
+
Ok(Self::new(rstring))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
#[derive(Debug)]
|
|
118
|
+
pub struct RStringMut<'a> {
|
|
119
|
+
inner: RString,
|
|
120
|
+
capa: Cell<usize>,
|
|
121
|
+
// Used to safely borrow the underlying rstring buffer by associating it with the lifetime of
|
|
122
|
+
// the RStringMut
|
|
123
|
+
_lifetime: PhantomData<&'a ()>,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
impl<'a> RStringMut<'a> {
|
|
127
|
+
pub(crate) fn buf_new(size: usize) -> Self {
|
|
128
|
+
let string = RString::buf_new(size);
|
|
129
|
+
Self {
|
|
130
|
+
inner: string,
|
|
131
|
+
capa: Cell::new(size),
|
|
132
|
+
_lifetime: PhantomData,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
pub(crate) fn as_mut_slice(&mut self) -> &'a mut [u8] {
|
|
137
|
+
let raw_value = self.inner.as_raw();
|
|
138
|
+
|
|
139
|
+
unsafe {
|
|
140
|
+
std::slice::from_raw_parts_mut(RSTRING_PTR(raw_value) as *mut u8, self.capa.get())
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
pub(crate) fn capacity(&self) -> usize {
|
|
145
|
+
self.capa.get()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
pub(crate) fn expand(&self, size: usize) {
|
|
149
|
+
if size <= self.capacity() {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
unsafe { rb_str_modify_expand(self.inner.as_raw(), size as _) };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
pub(crate) fn set_len(&self, len: usize) {
|
|
157
|
+
unsafe { rb_str_set_len(self.inner.as_raw(), len as _) }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
pub(crate) fn into_inner(self) -> RString {
|
|
161
|
+
self.inner
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
impl Drop for RStringMut<'_> {
|
|
166
|
+
fn drop(&mut self) {
|
|
167
|
+
// Keep the value alive while we hold this RString
|
|
168
|
+
let _ = rb_gc_guard!(self.inner.as_raw());
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
pub(crate) fn nogvl_if_large<F, R>(input_len: usize, mut func: F) -> R
|
|
173
|
+
where
|
|
174
|
+
F: FnMut() -> R,
|
|
175
|
+
R: Sized,
|
|
176
|
+
{
|
|
177
|
+
const MAX_INPUT_LEN: usize = 8192;
|
|
178
|
+
|
|
179
|
+
if input_len > MAX_INPUT_LEN {
|
|
180
|
+
nogvl(func)
|
|
181
|
+
} else {
|
|
182
|
+
func()
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// https://docs.rs/rb-sys/0.9.97/rb_sys/bindings/uncategorized/fn.rb_thread_call_without_gvl.html
|
|
187
|
+
pub(crate) fn nogvl<F, R>(mut func: F) -> R
|
|
188
|
+
where
|
|
189
|
+
F: FnMut() -> R,
|
|
190
|
+
R: Sized,
|
|
191
|
+
{
|
|
192
|
+
unsafe extern "C" fn call_without_gvl<F, R>(arg: *mut c_void) -> *mut c_void
|
|
193
|
+
where
|
|
194
|
+
F: FnMut() -> R,
|
|
195
|
+
R: Sized,
|
|
196
|
+
{
|
|
197
|
+
let arg = arg as *mut (&mut F, &mut MaybeUninit<R>);
|
|
198
|
+
// Safety: we know that the pointer is valid since we initialized it in nogvl
|
|
199
|
+
let (func, result) = unsafe { &mut *arg };
|
|
200
|
+
result.write(func());
|
|
201
|
+
|
|
202
|
+
null_mut()
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let result = MaybeUninit::uninit(); //location in memory that has not yet been initalized (init'd in call_without_gvl)
|
|
206
|
+
let arg_ptr = &(&mut func, &result) as *const _ as *mut c_void; //tuple of func and result (raw + mutable) pointers
|
|
207
|
+
|
|
208
|
+
unsafe {
|
|
209
|
+
// https://github.com/ruby/ruby/blob/ruby_3_3/thread.c#L1550-L1634
|
|
210
|
+
rb_thread_call_without_gvl(Some(call_without_gvl::<F, R>), arg_ptr, None, null_mut());
|
|
211
|
+
result.assume_init()
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
mod block;
|
|
2
|
+
mod header;
|
|
3
|
+
mod helpers;
|
|
4
|
+
|
|
5
|
+
pub(crate) use header::*;
|
|
6
|
+
pub(crate) use helpers::*;
|
|
7
|
+
|
|
8
|
+
use magnus::{
|
|
9
|
+
exception::standard_error,
|
|
10
|
+
function,
|
|
11
|
+
prelude::*,
|
|
12
|
+
value::{InnerValue, Lazy},
|
|
13
|
+
Error, ExceptionClass, RModule, Ruby,
|
|
14
|
+
};
|
|
15
|
+
use rb_sys::ruby_abi_version;
|
|
16
|
+
|
|
17
|
+
static MODULE_ROOT: Lazy<RModule> = Lazy::new(|ruby| ruby.define_module("Lz4Flex").unwrap());
|
|
18
|
+
|
|
19
|
+
pub(crate) fn base_error_class() -> ExceptionClass {
|
|
20
|
+
static BASE_ERROR_CLASS: Lazy<ExceptionClass> = Lazy::new(|ruby| {
|
|
21
|
+
MODULE_ROOT
|
|
22
|
+
.get_inner_with(ruby)
|
|
23
|
+
.define_error("Error", standard_error())
|
|
24
|
+
.unwrap()
|
|
25
|
+
});
|
|
26
|
+
unsafe { BASE_ERROR_CLASS.get_inner_with(&Ruby::get_unchecked()) }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
pub(crate) fn encode_error_class() -> ExceptionClass {
|
|
30
|
+
static ENCODE_ERROR_CLASS: Lazy<ExceptionClass> = Lazy::new(|ruby| {
|
|
31
|
+
MODULE_ROOT
|
|
32
|
+
.get_inner_with(ruby)
|
|
33
|
+
.define_error("EncodeError", base_error_class())
|
|
34
|
+
.unwrap()
|
|
35
|
+
});
|
|
36
|
+
unsafe { ENCODE_ERROR_CLASS.get_inner_with(&Ruby::get_unchecked()) }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
pub(crate) fn decode_error_class() -> ExceptionClass {
|
|
40
|
+
static DECODE_ERROR_CLASS: Lazy<ExceptionClass> = Lazy::new(|ruby| {
|
|
41
|
+
MODULE_ROOT
|
|
42
|
+
.get_inner_with(ruby)
|
|
43
|
+
.define_error("DecodeError", base_error_class())
|
|
44
|
+
.unwrap()
|
|
45
|
+
});
|
|
46
|
+
unsafe { DECODE_ERROR_CLASS.get_inner_with(&Ruby::get_unchecked()) }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
ruby_abi_version!();
|
|
50
|
+
|
|
51
|
+
#[magnus::init]
|
|
52
|
+
fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
53
|
+
let module = MODULE_ROOT.get_inner_with(ruby);
|
|
54
|
+
let _ = decode_error_class();
|
|
55
|
+
let _ = encode_error_class();
|
|
56
|
+
|
|
57
|
+
module.define_singleton_method("compress", function!(block::compress, 1))?;
|
|
58
|
+
module.define_singleton_method("decompress", function!(block::decompress, 1))?;
|
|
59
|
+
module
|
|
60
|
+
.singleton_class()?
|
|
61
|
+
.define_alias("deflate", "compress")?;
|
|
62
|
+
module
|
|
63
|
+
.singleton_class()?
|
|
64
|
+
.define_alias("inflate", "decompress")?;
|
|
65
|
+
|
|
66
|
+
let varint_module = module.define_module("VarInt")?;
|
|
67
|
+
varint_module.define_singleton_method("compress", function!(block::compress_varint, 1))?;
|
|
68
|
+
varint_module.define_singleton_method("decompress", function!(block::decompress_varint, 1))?;
|
|
69
|
+
|
|
70
|
+
Ok(())
|
|
71
|
+
}
|
data/lib/lz4_flex.rb
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Tries to require the precompiled extension for the given Ruby version first
|
|
5
|
+
begin
|
|
6
|
+
RUBY_VERSION =~ /(\d+\.\d+)/
|
|
7
|
+
require "lz4_flex/#{Regexp.last_match(1)}/lz4_flex_ext"
|
|
8
|
+
rescue LoadError
|
|
9
|
+
require_relative "lz4_flex/lz4_flex_ext"
|
|
10
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lz4_flex
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1.pre2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Shopify Engineering
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2024-08-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rb_sys
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.9.101
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.9.101
|
|
27
|
+
description: A modern LZ4 compression library for Ruby, leveraging the power of the
|
|
28
|
+
[`lz4_flex`](https://github.com/PSeitz/lz4_flex) Rust crate. This library provides
|
|
29
|
+
a pure Rust implementation of the LZ4 algorithm, ensuring high performance and safety.
|
|
30
|
+
email:
|
|
31
|
+
- gems@shopify.com
|
|
32
|
+
executables: []
|
|
33
|
+
extensions:
|
|
34
|
+
- ext/lz4_flex_ext/extconf.rb
|
|
35
|
+
extra_rdoc_files: []
|
|
36
|
+
files:
|
|
37
|
+
- Cargo.lock
|
|
38
|
+
- Cargo.toml
|
|
39
|
+
- LICENSE.md
|
|
40
|
+
- README.md
|
|
41
|
+
- ext/lz4_flex_ext/Cargo.toml
|
|
42
|
+
- ext/lz4_flex_ext/extconf.rb
|
|
43
|
+
- ext/lz4_flex_ext/src/block.rs
|
|
44
|
+
- ext/lz4_flex_ext/src/header.rs
|
|
45
|
+
- ext/lz4_flex_ext/src/helpers.rs
|
|
46
|
+
- ext/lz4_flex_ext/src/lib.rs
|
|
47
|
+
- lib/lz4_flex.rb
|
|
48
|
+
- lib/lz4_flex/version.rb
|
|
49
|
+
homepage: https://github.com/Shopify/lz4-flex-rb
|
|
50
|
+
licenses:
|
|
51
|
+
- MIT
|
|
52
|
+
metadata:
|
|
53
|
+
allowed_push_host: https://rubygems.org
|
|
54
|
+
homepage_uri: https://github.com/Shopify/lz4-flex-rb
|
|
55
|
+
source_code_uri: https://github.com/Shopify/lz4-flex-rb
|
|
56
|
+
changelog_uri: https://github.com/Shopify/lz4-flex-rb/releases
|
|
57
|
+
post_install_message:
|
|
58
|
+
rdoc_options: []
|
|
59
|
+
require_paths:
|
|
60
|
+
- lib
|
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '3.1'
|
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '0'
|
|
71
|
+
requirements: []
|
|
72
|
+
rubygems_version: 3.5.3
|
|
73
|
+
signing_key:
|
|
74
|
+
specification_version: 4
|
|
75
|
+
summary: A modern LZ4 compression library for Ruby, leveraging the `lz4_flex` Rust
|
|
76
|
+
crate.
|
|
77
|
+
test_files: []
|