fastcrc 0.1.0

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.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ require "rb_sys/extensiontask"
13
+
14
+ task build: :compile
15
+
16
+ GEMSPEC = Gem::Specification.load("fastcrc.gemspec")
17
+
18
+ RbSys::ExtensionTask.new("fastcrc", GEMSPEC) do |ext|
19
+ ext.lib_dir = "lib/fastcrc"
20
+ end
21
+
22
+ desc "Build and publish the gem to RubyGems"
23
+ task publish: :build do
24
+ sh "gem", "push", File.join("pkg", "#{GEMSPEC.full_name}.gem")
25
+ end
26
+
27
+ namespace :benchmark do
28
+ desc "Benchmark FastCRC against digest-crc"
29
+ task digest_crc: :compile do
30
+ ruby "benchmark/digest_crc.rb"
31
+ end
32
+ end
33
+
34
+ task default: %i[compile test rubocop]
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "benchmark"
5
+ require "bundler/setup"
6
+ require "fastcrc"
7
+
8
+ DEFAULT_ITERATIONS = 10
9
+ DEFAULT_SAMPLE_COUNT = 1_000
10
+ DEFAULT_BLOCK_SIZE = 8 * 1024
11
+
12
+ ITERATIONS = Integer(ENV.fetch("ITERATIONS", DEFAULT_ITERATIONS))
13
+ SAMPLE_COUNT = Integer(ENV.fetch("SAMPLE_COUNT", DEFAULT_SAMPLE_COUNT))
14
+ BLOCK_SIZE = Integer(ENV.fetch("BLOCK_SIZE", DEFAULT_BLOCK_SIZE))
15
+
16
+ SAMPLES = Array.new(SAMPLE_COUNT) do |sample_index|
17
+ Random.new(sample_index).bytes(BLOCK_SIZE).b
18
+ end.freeze
19
+
20
+ BENCHMARKS = [
21
+ ["CRC16", "crc16", "CRC16"],
22
+ ["CRC16 CCITT", "crc16_ccitt", "CRC16CCITT"],
23
+ ["CRC16 DNP", "crc16_dnp", "CRC16DNP"],
24
+ ["CRC16 Genibus", "crc16_genibus", "CRC16Genibus"],
25
+ ["CRC16 Kermit", "crc16_kermit", "CRC16Kermit"],
26
+ ["CRC16 Modbus", "crc16_modbus", "CRC16Modbus"],
27
+ ["CRC16 QT", "crc16_qt", "CRC16QT"],
28
+ ["CRC16 USB", "crc16_usb", "CRC16USB"],
29
+ ["CRC16 X25", "crc16_x_25", "CRC16X25"],
30
+ ["CRC16 XModem", "crc16_xmodem", "CRC16XModem"],
31
+ ["CRC16 ZModem", "crc16_zmodem", "CRC16ZModem"],
32
+ ["CRC32", "crc32", "CRC32"],
33
+ ["CRC32 BZip2", "crc32_bzip2", "CRC32BZip2"],
34
+ ["CRC32c", "crc32c", "CRC32c"],
35
+ ["CRC32 Jam", "crc32_jam", "CRC32Jam"],
36
+ ["CRC32 MPEG", "crc32_mpeg", "CRC32MPEG"],
37
+ ["CRC32 POSIX", "crc32_posix", "CRC32POSIX"],
38
+ ["CRC32 XFER", "crc32_xfer", "CRC32XFER"],
39
+ ["CRC64", "crc64", "CRC64"],
40
+ ["CRC64 Jones", "crc64_jones", "CRC64Jones"],
41
+ ["CRC64 NVMe", "crc64_nvme", "CRC64NVMe"],
42
+ ["CRC64 XZ", "crc64_xz", "CRC64XZ"]
43
+ ].map do |label, require_path, class_name|
44
+ require "digest/#{require_path}"
45
+
46
+ {
47
+ label: label,
48
+ fastcrc_class: FastCRC.const_get(class_name),
49
+ digest_crc_class: Digest.const_get(class_name)
50
+ }
51
+ end.freeze
52
+
53
+ def verify_matching_checksums!(fastcrc_class, digest_crc_class)
54
+ SAMPLES.each do |sample|
55
+ next if fastcrc_class.hexdigest(sample) == digest_crc_class.hexdigest(sample)
56
+
57
+ raise "#{fastcrc_class} and #{digest_crc_class} produced different checksums"
58
+ end
59
+ end
60
+
61
+ def update_all(digest)
62
+ SAMPLES.each { |sample| digest.update(sample) }
63
+ digest.hexdigest
64
+ end
65
+
66
+ puts "Ruby #{RUBY_VERSION} (#{RUBY_ENGINE})"
67
+ puts "digest-crc #{Gem.loaded_specs.fetch("digest-crc").version}"
68
+ puts "Samples: #{SAMPLE_COUNT} x #{BLOCK_SIZE} bytes"
69
+ puts "Iterations: #{ITERATIONS}"
70
+
71
+ BENCHMARKS.each do |benchmark|
72
+ puts "\n#{benchmark.fetch(:label)}"
73
+
74
+ fastcrc_class = benchmark.fetch(:fastcrc_class)
75
+ digest_crc_class = benchmark.fetch(:digest_crc_class)
76
+
77
+ verify_matching_checksums!(fastcrc_class, digest_crc_class)
78
+
79
+ Benchmark.bm(28) do |runner|
80
+ runner.report("#{fastcrc_class}#update") do
81
+ ITERATIONS.times { update_all(fastcrc_class.new) }
82
+ end
83
+
84
+ runner.report("#{digest_crc_class}#update") do
85
+ ITERATIONS.times { update_all(digest_crc_class.new) }
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,13 @@
1
+ [package]
2
+ name = "fastcrc"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ license = "MIT"
6
+ publish = false
7
+
8
+ [lib]
9
+ crate-type = ["cdylib"]
10
+
11
+ [dependencies]
12
+ crc-fast = { version = "1.10.0", default-features = false, features = ["std"] }
13
+ magnus = { version = "0.8.2" }
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+ require "rb_sys/mkmf"
5
+
6
+ create_rust_makefile("fastcrc/fastcrc")
@@ -0,0 +1,477 @@
1
+ use crc_fast::{checksum, checksum_with_params, CrcAlgorithm, CrcParams, Digest};
2
+ use magnus::{function, method, prelude::*, Error, RClass, RString, Ruby};
3
+ use std::cell::RefCell;
4
+
5
+ fn bytes_from_rstring(input: &RString) -> &[u8] {
6
+ // Safe because we do not yield to Ruby while holding the slice reference.
7
+ unsafe { input.as_slice() }
8
+ }
9
+
10
+ fn format_checksum(checksum: u64, hex_width: usize) -> String {
11
+ format!("{:0width$x}", checksum, width = hex_width)
12
+ }
13
+
14
+ fn crc64_params() -> CrcParams {
15
+ CrcParams::new(
16
+ "CRC-64",
17
+ 64,
18
+ 0x0000_0000_0000_001b,
19
+ 0x0000_0000_0000_0000,
20
+ true,
21
+ 0x0000_0000_0000_0000,
22
+ 0x46a5_a938_8a5b_effe,
23
+ )
24
+ }
25
+
26
+ fn crc64_jones_params() -> CrcParams {
27
+ CrcParams::new(
28
+ "CRC-64/JONES",
29
+ 64,
30
+ 0xad93_d235_94c9_35a9,
31
+ 0xffff_ffff_ffff_ffff,
32
+ true,
33
+ 0x0000_0000_0000_0000,
34
+ 0xcaa7_1716_8609_f281,
35
+ )
36
+ }
37
+
38
+ macro_rules! impl_crc_methods {
39
+ ($struct_name:ident, $hex_width:expr) => {
40
+ impl_crc_methods!($struct_name, $hex_width, 0u64);
41
+ };
42
+
43
+ ($struct_name:ident, $hex_width:expr, $hexdigest_xor:expr) => {
44
+ fn update(&self, input: RString) {
45
+ self.digest.borrow_mut().update(bytes_from_rstring(&input));
46
+ }
47
+
48
+ fn checksum(&self) -> u64 {
49
+ self.digest.borrow().finalize()
50
+ }
51
+
52
+ fn hexdigest(&self) -> String {
53
+ format_checksum(self.checksum() ^ $hexdigest_xor, $hex_width)
54
+ }
55
+
56
+ fn reset(&self) {
57
+ self.digest.borrow_mut().reset();
58
+ }
59
+ };
60
+ }
61
+
62
+ macro_rules! define_known_crc {
63
+ ($struct_name:ident, $ruby_class:literal, $algorithm:expr, $hex_width:expr) => {
64
+ #[magnus::wrap(class = $ruby_class, free_immediately, size)]
65
+ struct $struct_name {
66
+ digest: RefCell<Digest>,
67
+ }
68
+
69
+ impl $struct_name {
70
+ fn new() -> Self {
71
+ Self {
72
+ digest: RefCell::new(Digest::new($algorithm)),
73
+ }
74
+ }
75
+
76
+ fn checksum_once(input: RString) -> u64 {
77
+ checksum($algorithm, bytes_from_rstring(&input))
78
+ }
79
+
80
+ fn hexdigest_once(input: RString) -> String {
81
+ format_checksum(Self::checksum_once(input), $hex_width)
82
+ }
83
+
84
+ impl_crc_methods!($struct_name, $hex_width);
85
+ }
86
+ };
87
+ }
88
+
89
+ macro_rules! define_custom_crc {
90
+ ($struct_name:ident, $ruby_class:literal, $params_fn:ident, $hex_width:expr) => {
91
+ define_custom_crc!($struct_name, $ruby_class, $params_fn, $hex_width, 0u64);
92
+ };
93
+
94
+ (
95
+ $struct_name:ident,
96
+ $ruby_class:literal,
97
+ $params_fn:ident,
98
+ $hex_width:expr,
99
+ $hexdigest_xor:expr
100
+ ) => {
101
+ #[magnus::wrap(class = $ruby_class, free_immediately, size)]
102
+ struct $struct_name {
103
+ digest: RefCell<Digest>,
104
+ }
105
+
106
+ impl $struct_name {
107
+ fn new() -> Self {
108
+ Self {
109
+ digest: RefCell::new(Digest::new_with_params($params_fn())),
110
+ }
111
+ }
112
+
113
+ fn checksum_once(input: RString) -> u64 {
114
+ checksum_with_params($params_fn(), bytes_from_rstring(&input))
115
+ }
116
+
117
+ fn hexdigest_once(input: RString) -> String {
118
+ format_checksum(Self::checksum_once(input) ^ $hexdigest_xor, $hex_width)
119
+ }
120
+
121
+ impl_crc_methods!($struct_name, $hex_width, $hexdigest_xor);
122
+ }
123
+ };
124
+ }
125
+
126
+ macro_rules! register_crc_class {
127
+ (
128
+ $module:expr,
129
+ $ruby:expr,
130
+ $class_name:literal,
131
+ $struct_name:ident,
132
+ $width:expr,
133
+ $check:expr,
134
+ $catalog_name:literal
135
+ ) => {{
136
+ let class = $module.define_class($class_name, $ruby.class_object())?;
137
+ class.define_singleton_method("new", function!($struct_name::new, 0))?;
138
+ class.define_singleton_method("checksum", function!($struct_name::checksum_once, 1))?;
139
+ class.define_singleton_method("hexdigest", function!($struct_name::hexdigest_once, 1))?;
140
+ class.define_method("update", method!($struct_name::update, 1))?;
141
+ class.define_method("checksum", method!($struct_name::checksum, 0))?;
142
+ class.define_method("hexdigest", method!($struct_name::hexdigest, 0))?;
143
+ class.define_method("reset", method!($struct_name::reset, 0))?;
144
+ class.const_set("WIDTH", $width)?;
145
+ class.const_set("CHECK", $check)?;
146
+ class.const_set("NAME", $catalog_name)?;
147
+ class
148
+ }};
149
+ }
150
+
151
+ fn crc16_dnp_table_entry(index: u8) -> u16 {
152
+ let mut value = u16::from(index);
153
+
154
+ for _ in 0..8 {
155
+ value = if value & 1 == 1 {
156
+ (value >> 1) ^ 0xa6bc
157
+ } else {
158
+ value >> 1
159
+ };
160
+ }
161
+
162
+ value
163
+ }
164
+
165
+ fn crc16_dnp_update(mut checksum: u16, data: &[u8]) -> u16 {
166
+ for byte in data {
167
+ let table_index = ((checksum ^ u16::from(*byte)) & 0xff) as u8;
168
+ checksum = ((((u32::from(checksum)) << 8) ^ u32::from(crc16_dnp_table_entry(table_index)))
169
+ & 0xffff) as u16;
170
+ }
171
+
172
+ checksum
173
+ }
174
+
175
+ #[magnus::wrap(class = "FastCRC::CRC16DNP", free_immediately, size)]
176
+ struct Crc16Dnp {
177
+ checksum: RefCell<u16>,
178
+ }
179
+
180
+ impl Crc16Dnp {
181
+ fn new() -> Self {
182
+ Self {
183
+ checksum: RefCell::new(0),
184
+ }
185
+ }
186
+
187
+ fn checksum_once(input: RString) -> u64 {
188
+ u64::from(crc16_dnp_update(0, bytes_from_rstring(&input)))
189
+ }
190
+
191
+ fn hexdigest_once(input: RString) -> String {
192
+ format_checksum(Self::checksum_once(input) ^ 0xffff, 4)
193
+ }
194
+
195
+ fn update(&self, input: RString) {
196
+ let mut checksum = self.checksum.borrow_mut();
197
+ *checksum = crc16_dnp_update(*checksum, bytes_from_rstring(&input));
198
+ }
199
+
200
+ fn checksum(&self) -> u64 {
201
+ u64::from(*self.checksum.borrow())
202
+ }
203
+
204
+ fn hexdigest(&self) -> String {
205
+ format_checksum(self.checksum() ^ 0xffff, 4)
206
+ }
207
+
208
+ fn reset(&self) {
209
+ *self.checksum.borrow_mut() = 0;
210
+ }
211
+ }
212
+
213
+ define_known_crc!(Crc16, "FastCRC::CRC16", CrcAlgorithm::Crc16Arc, 4);
214
+ define_known_crc!(
215
+ Crc16Ccitt,
216
+ "FastCRC::CRC16CCITT",
217
+ CrcAlgorithm::Crc16Ibm3740,
218
+ 4
219
+ );
220
+ define_known_crc!(
221
+ Crc16Genibus,
222
+ "FastCRC::CRC16Genibus",
223
+ CrcAlgorithm::Crc16Genibus,
224
+ 4
225
+ );
226
+ define_known_crc!(
227
+ Crc16Kermit,
228
+ "FastCRC::CRC16Kermit",
229
+ CrcAlgorithm::Crc16Kermit,
230
+ 4
231
+ );
232
+ define_known_crc!(
233
+ Crc16Modbus,
234
+ "FastCRC::CRC16Modbus",
235
+ CrcAlgorithm::Crc16Modbus,
236
+ 4
237
+ );
238
+ define_known_crc!(Crc16Qt, "FastCRC::CRC16QT", CrcAlgorithm::Crc16IbmSdlc, 4);
239
+ define_known_crc!(Crc16Usb, "FastCRC::CRC16USB", CrcAlgorithm::Crc16Usb, 4);
240
+ define_known_crc!(Crc16X25, "FastCRC::CRC16X25", CrcAlgorithm::Crc16IbmSdlc, 4);
241
+ define_known_crc!(
242
+ Crc16XModem,
243
+ "FastCRC::CRC16XModem",
244
+ CrcAlgorithm::Crc16Xmodem,
245
+ 4
246
+ );
247
+ define_known_crc!(
248
+ Crc16ZModem,
249
+ "FastCRC::CRC16ZModem",
250
+ CrcAlgorithm::Crc16Xmodem,
251
+ 4
252
+ );
253
+
254
+ define_known_crc!(Crc32, "FastCRC::CRC32", CrcAlgorithm::Crc32IsoHdlc, 8);
255
+ define_known_crc!(
256
+ Crc32Bzip2,
257
+ "FastCRC::CRC32BZip2",
258
+ CrcAlgorithm::Crc32Bzip2,
259
+ 8
260
+ );
261
+ define_known_crc!(Crc32C, "FastCRC::CRC32c", CrcAlgorithm::Crc32Iscsi, 8);
262
+ define_known_crc!(Crc32Jam, "FastCRC::CRC32Jam", CrcAlgorithm::Crc32Jamcrc, 8);
263
+ define_known_crc!(Crc32Mpeg, "FastCRC::CRC32MPEG", CrcAlgorithm::Crc32Mpeg2, 8);
264
+ define_known_crc!(
265
+ Crc32Posix,
266
+ "FastCRC::CRC32POSIX",
267
+ CrcAlgorithm::Crc32Cksum,
268
+ 8
269
+ );
270
+ define_known_crc!(Crc32Xfer, "FastCRC::CRC32XFER", CrcAlgorithm::Crc32Xfer, 8);
271
+
272
+ define_custom_crc!(Crc64, "FastCRC::CRC64", crc64_params, 16);
273
+ define_custom_crc!(Crc64Jones, "FastCRC::CRC64Jones", crc64_jones_params, 16);
274
+ define_known_crc!(Crc64Nvme, "FastCRC::CRC64NVMe", CrcAlgorithm::Crc64Nvme, 16);
275
+ define_known_crc!(Crc64Xz, "FastCRC::CRC64XZ", CrcAlgorithm::Crc64Xz, 16);
276
+
277
+ #[magnus::init]
278
+ fn init(ruby: &Ruby) -> Result<(), Error> {
279
+ let fast_crc = ruby.define_module("FastCRC")?;
280
+
281
+ register_crc_class!(fast_crc, ruby, "CRC16", Crc16, 16, 0xbb3du64, "CRC-16/ARC");
282
+ register_crc_class!(
283
+ fast_crc,
284
+ ruby,
285
+ "CRC16CCITT",
286
+ Crc16Ccitt,
287
+ 16,
288
+ 0x29b1u64,
289
+ "CRC-16/IBM-3740"
290
+ );
291
+ register_crc_class!(
292
+ fast_crc,
293
+ ruby,
294
+ "CRC16DNP",
295
+ Crc16Dnp,
296
+ 16,
297
+ 0xbeffu64,
298
+ "CRC-16/DNP"
299
+ );
300
+ register_crc_class!(
301
+ fast_crc,
302
+ ruby,
303
+ "CRC16Genibus",
304
+ Crc16Genibus,
305
+ 16,
306
+ 0xd64eu64,
307
+ "CRC-16/GENIBUS"
308
+ );
309
+ register_crc_class!(
310
+ fast_crc,
311
+ ruby,
312
+ "CRC16Kermit",
313
+ Crc16Kermit,
314
+ 16,
315
+ 0x2189u64,
316
+ "CRC-16/KERMIT"
317
+ );
318
+ register_crc_class!(
319
+ fast_crc,
320
+ ruby,
321
+ "CRC16Modbus",
322
+ Crc16Modbus,
323
+ 16,
324
+ 0x4b37u64,
325
+ "CRC-16/MODBUS"
326
+ );
327
+ register_crc_class!(
328
+ fast_crc,
329
+ ruby,
330
+ "CRC16QT",
331
+ Crc16Qt,
332
+ 16,
333
+ 0x906eu64,
334
+ "CRC-16/IBM-SDLC"
335
+ );
336
+ register_crc_class!(
337
+ fast_crc,
338
+ ruby,
339
+ "CRC16USB",
340
+ Crc16Usb,
341
+ 16,
342
+ 0xb4c8u64,
343
+ "CRC-16/USB"
344
+ );
345
+ register_crc_class!(
346
+ fast_crc,
347
+ ruby,
348
+ "CRC16X25",
349
+ Crc16X25,
350
+ 16,
351
+ 0x906eu64,
352
+ "CRC-16/IBM-SDLC"
353
+ );
354
+ register_crc_class!(
355
+ fast_crc,
356
+ ruby,
357
+ "CRC16XModem",
358
+ Crc16XModem,
359
+ 16,
360
+ 0x31c3u64,
361
+ "CRC-16/XMODEM"
362
+ );
363
+ register_crc_class!(
364
+ fast_crc,
365
+ ruby,
366
+ "CRC16ZModem",
367
+ Crc16ZModem,
368
+ 16,
369
+ 0x31c3u64,
370
+ "CRC-16/XMODEM"
371
+ );
372
+
373
+ register_crc_class!(
374
+ fast_crc,
375
+ ruby,
376
+ "CRC32",
377
+ Crc32,
378
+ 32,
379
+ 0xcbf4_3926u64,
380
+ "CRC-32/ISO-HDLC"
381
+ );
382
+ register_crc_class!(
383
+ fast_crc,
384
+ ruby,
385
+ "CRC32BZip2",
386
+ Crc32Bzip2,
387
+ 32,
388
+ 0xfc89_1918u64,
389
+ "CRC-32/BZIP2"
390
+ );
391
+ register_crc_class!(
392
+ fast_crc,
393
+ ruby,
394
+ "CRC32c",
395
+ Crc32C,
396
+ 32,
397
+ 0xe306_9283u64,
398
+ "CRC-32/ISCSI"
399
+ );
400
+ register_crc_class!(
401
+ fast_crc,
402
+ ruby,
403
+ "CRC32Jam",
404
+ Crc32Jam,
405
+ 32,
406
+ 0x340b_c6d9u64,
407
+ "CRC-32/JAMCRC"
408
+ );
409
+ let crc32_mpeg: RClass = register_crc_class!(
410
+ fast_crc,
411
+ ruby,
412
+ "CRC32MPEG",
413
+ Crc32Mpeg,
414
+ 32,
415
+ 0x0376_e6e7u64,
416
+ "CRC-32/MPEG-2"
417
+ );
418
+ register_crc_class!(
419
+ fast_crc,
420
+ ruby,
421
+ "CRC32POSIX",
422
+ Crc32Posix,
423
+ 32,
424
+ 0x765e_7680u64,
425
+ "CRC-32/CKSUM"
426
+ );
427
+ register_crc_class!(
428
+ fast_crc,
429
+ ruby,
430
+ "CRC32XFER",
431
+ Crc32Xfer,
432
+ 32,
433
+ 0xbd0b_e338u64,
434
+ "CRC-32/XFER"
435
+ );
436
+
437
+ register_crc_class!(
438
+ fast_crc,
439
+ ruby,
440
+ "CRC64",
441
+ Crc64,
442
+ 64,
443
+ 0x46a5_a938_8a5b_effe_u64,
444
+ "CRC-64"
445
+ );
446
+ register_crc_class!(
447
+ fast_crc,
448
+ ruby,
449
+ "CRC64Jones",
450
+ Crc64Jones,
451
+ 64,
452
+ 0xcaa7_1716_8609_f281u64,
453
+ "CRC-64/JONES"
454
+ );
455
+ register_crc_class!(
456
+ fast_crc,
457
+ ruby,
458
+ "CRC64NVMe",
459
+ Crc64Nvme,
460
+ 64,
461
+ 0xae8b_1486_0a79_9888u64,
462
+ "CRC-64/NVME"
463
+ );
464
+ register_crc_class!(
465
+ fast_crc,
466
+ ruby,
467
+ "CRC64XZ",
468
+ Crc64Xz,
469
+ 64,
470
+ 0x995d_c9bb_df19_39fau64,
471
+ "CRC-64/XZ"
472
+ );
473
+
474
+ fast_crc.const_set("CRC32Mpeg", crc32_mpeg)?;
475
+
476
+ Ok(())
477
+ }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FastCRC
4
+ VERSION = "0.1.0"
5
+ end
data/lib/fastcrc.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "fastcrc/version"
4
+ require "fastcrc/fastcrc"
5
+
6
+ module FastCRC
7
+ class Error < StandardError; end
8
+ end
data/mise.lock ADDED
@@ -0,0 +1,37 @@
1
+ # @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
2
+
3
+ [[tools.ruby]]
4
+ version = "4.0.5"
5
+ backend = "core:ruby"
6
+
7
+ [tools.ruby."platforms.linux-arm64"]
8
+ checksum = "sha256:7d6149079a63f8ae1d326c9fa65c6019ba2dc3155eae7b39159817911c88958e"
9
+ url = "https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.5.tar.gz"
10
+
11
+ [tools.ruby."platforms.linux-arm64-musl"]
12
+ checksum = "sha256:7d6149079a63f8ae1d326c9fa65c6019ba2dc3155eae7b39159817911c88958e"
13
+ url = "https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.5.tar.gz"
14
+
15
+ [tools.ruby."platforms.linux-x64"]
16
+ checksum = "sha256:7d6149079a63f8ae1d326c9fa65c6019ba2dc3155eae7b39159817911c88958e"
17
+ url = "https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.5.tar.gz"
18
+
19
+ [tools.ruby."platforms.linux-x64-musl"]
20
+ checksum = "sha256:7d6149079a63f8ae1d326c9fa65c6019ba2dc3155eae7b39159817911c88958e"
21
+ url = "https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.5.tar.gz"
22
+
23
+ [tools.ruby."platforms.macos-arm64"]
24
+ checksum = "sha256:7d6149079a63f8ae1d326c9fa65c6019ba2dc3155eae7b39159817911c88958e"
25
+ url = "https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.5.tar.gz"
26
+
27
+ [tools.ruby."platforms.macos-x64"]
28
+ checksum = "sha256:7d6149079a63f8ae1d326c9fa65c6019ba2dc3155eae7b39159817911c88958e"
29
+ url = "https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.5.tar.gz"
30
+
31
+ [tools.ruby."platforms.windows-x64"]
32
+ checksum = "sha256:74e31613fc71e6e23431dfc4d8b6ec2818a4dc1fd16e0983b074144c16719c8b"
33
+ url = "https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-4.0.5-1/rubyinstaller-4.0.5-1-x64.7z"
34
+
35
+ [[tools.rust]]
36
+ version = "1.96.0"
37
+ backend = "core:rust"
data/mise.toml ADDED
@@ -0,0 +1,3 @@
1
+ [tools]
2
+ ruby = "latest"
3
+ rust = "latest"