uncle_blake3 0.0.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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +27 -0
  3. data/README.md +89 -0
  4. data/ext/Rakefile +55 -0
  5. data/ext/binding/uncle_blake3.c +41 -0
  6. data/ext/blake3/c/Makefile.testing +82 -0
  7. data/ext/blake3/c/README.md +316 -0
  8. data/ext/blake3/c/blake3.c +616 -0
  9. data/ext/blake3/c/blake3.h +60 -0
  10. data/ext/blake3/c/blake3_avx2.c +326 -0
  11. data/ext/blake3/c/blake3_avx2_x86-64_unix.S +1815 -0
  12. data/ext/blake3/c/blake3_avx2_x86-64_windows_gnu.S +1817 -0
  13. data/ext/blake3/c/blake3_avx2_x86-64_windows_msvc.asm +1828 -0
  14. data/ext/blake3/c/blake3_avx512.c +1207 -0
  15. data/ext/blake3/c/blake3_avx512_x86-64_unix.S +2585 -0
  16. data/ext/blake3/c/blake3_avx512_x86-64_windows_gnu.S +2615 -0
  17. data/ext/blake3/c/blake3_avx512_x86-64_windows_msvc.asm +2634 -0
  18. data/ext/blake3/c/blake3_dispatch.c +276 -0
  19. data/ext/blake3/c/blake3_impl.h +282 -0
  20. data/ext/blake3/c/blake3_neon.c +351 -0
  21. data/ext/blake3/c/blake3_portable.c +160 -0
  22. data/ext/blake3/c/blake3_sse2.c +566 -0
  23. data/ext/blake3/c/blake3_sse2_x86-64_unix.S +2291 -0
  24. data/ext/blake3/c/blake3_sse2_x86-64_windows_gnu.S +2332 -0
  25. data/ext/blake3/c/blake3_sse2_x86-64_windows_msvc.asm +2350 -0
  26. data/ext/blake3/c/blake3_sse41.c +560 -0
  27. data/ext/blake3/c/blake3_sse41_x86-64_unix.S +2028 -0
  28. data/ext/blake3/c/blake3_sse41_x86-64_windows_gnu.S +2069 -0
  29. data/ext/blake3/c/blake3_sse41_x86-64_windows_msvc.asm +2089 -0
  30. data/ext/blake3/c/example.c +37 -0
  31. data/ext/blake3/c/main.c +166 -0
  32. data/ext/blake3/c/test.py +97 -0
  33. data/lib/uncle_blake3/binding.rb +20 -0
  34. data/lib/uncle_blake3/build/loader.rb +40 -0
  35. data/lib/uncle_blake3/build/platform.rb +37 -0
  36. data/lib/uncle_blake3/build.rb +4 -0
  37. data/lib/uncle_blake3/digest.rb +119 -0
  38. data/lib/uncle_blake3/version.rb +5 -0
  39. data/lib/uncle_blake3.rb +7 -0
  40. metadata +112 -0
@@ -0,0 +1,37 @@
1
+ #include "blake3.h"
2
+ #include <errno.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+ #include <unistd.h>
7
+
8
+ int main() {
9
+ // Initialize the hasher.
10
+ blake3_hasher hasher;
11
+ blake3_hasher_init(&hasher);
12
+
13
+ // Read input bytes from stdin.
14
+ unsigned char buf[65536];
15
+ while (1) {
16
+ ssize_t n = read(STDIN_FILENO, buf, sizeof(buf));
17
+ if (n > 0) {
18
+ blake3_hasher_update(&hasher, buf, n);
19
+ } else if (n == 0) {
20
+ break; // end of file
21
+ } else {
22
+ fprintf(stderr, "read failed: %s\n", strerror(errno));
23
+ exit(1);
24
+ }
25
+ }
26
+
27
+ // Finalize the hash. BLAKE3_OUT_LEN is the default output length, 32 bytes.
28
+ uint8_t output[BLAKE3_OUT_LEN];
29
+ blake3_hasher_finalize(&hasher, output, BLAKE3_OUT_LEN);
30
+
31
+ // Print the hash as hexadecimal.
32
+ for (size_t i = 0; i < BLAKE3_OUT_LEN; i++) {
33
+ printf("%02x", output[i]);
34
+ }
35
+ printf("\n");
36
+ return 0;
37
+ }
@@ -0,0 +1,166 @@
1
+ /*
2
+ * This main file is intended for testing via `make test`. It does not build in
3
+ * other settings. See README.md in this directory for examples of how to build
4
+ * C code.
5
+ */
6
+
7
+ #include <assert.h>
8
+ #include <errno.h>
9
+ #include <stdbool.h>
10
+ #include <stdint.h>
11
+ #include <stdio.h>
12
+ #include <stdlib.h>
13
+
14
+ #include "blake3.h"
15
+ #include "blake3_impl.h"
16
+
17
+ #define HASH_MODE 0
18
+ #define KEYED_HASH_MODE 1
19
+ #define DERIVE_KEY_MODE 2
20
+
21
+ static void hex_char_value(uint8_t c, uint8_t *value, bool *valid) {
22
+ if ('0' <= c && c <= '9') {
23
+ *value = c - '0';
24
+ *valid = true;
25
+ } else if ('a' <= c && c <= 'f') {
26
+ *value = 10 + c - 'a';
27
+ *valid = true;
28
+ } else {
29
+ *valid = false;
30
+ }
31
+ }
32
+
33
+ static int parse_key(char *hex_key, uint8_t out[BLAKE3_KEY_LEN]) {
34
+ size_t hex_len = strlen(hex_key);
35
+ if (hex_len != 64) {
36
+ fprintf(stderr, "Expected a 64-char hexadecimal key, got %zu chars.\n",
37
+ hex_len);
38
+ return 1;
39
+ }
40
+ for (size_t i = 0; i < 64; i++) {
41
+ uint8_t value;
42
+ bool valid;
43
+ hex_char_value(hex_key[i], &value, &valid);
44
+ if (!valid) {
45
+ fprintf(stderr, "Invalid hex char.\n");
46
+ return 1;
47
+ }
48
+ if (i % 2 == 0) {
49
+ out[i / 2] = 0;
50
+ value <<= 4;
51
+ }
52
+ out[i / 2] += value;
53
+ }
54
+ return 0;
55
+ }
56
+
57
+ /* A little repetition here */
58
+ enum cpu_feature {
59
+ SSE2 = 1 << 0,
60
+ SSSE3 = 1 << 1,
61
+ SSE41 = 1 << 2,
62
+ AVX = 1 << 3,
63
+ AVX2 = 1 << 4,
64
+ AVX512F = 1 << 5,
65
+ AVX512VL = 1 << 6,
66
+ /* ... */
67
+ UNDEFINED = 1 << 30
68
+ };
69
+
70
+ extern enum cpu_feature g_cpu_features;
71
+ enum cpu_feature get_cpu_features(void);
72
+
73
+ int main(int argc, char **argv) {
74
+ size_t out_len = BLAKE3_OUT_LEN;
75
+ uint8_t key[BLAKE3_KEY_LEN];
76
+ char *context = "";
77
+ uint8_t mode = HASH_MODE;
78
+ while (argc > 1) {
79
+ if (argc <= 2) {
80
+ fprintf(stderr, "Odd number of arguments.\n");
81
+ return 1;
82
+ }
83
+ if (strcmp("--length", argv[1]) == 0) {
84
+ char *endptr = NULL;
85
+ errno = 0;
86
+ unsigned long long out_len_ll = strtoull(argv[2], &endptr, 10);
87
+ if (errno != 0 || out_len_ll > SIZE_MAX || endptr == argv[2] ||
88
+ *endptr != 0) {
89
+ fprintf(stderr, "Bad length argument.\n");
90
+ return 1;
91
+ }
92
+ out_len = (size_t)out_len_ll;
93
+ } else if (strcmp("--keyed", argv[1]) == 0) {
94
+ mode = KEYED_HASH_MODE;
95
+ int ret = parse_key(argv[2], key);
96
+ if (ret != 0) {
97
+ return ret;
98
+ }
99
+ } else if (strcmp("--derive-key", argv[1]) == 0) {
100
+ mode = DERIVE_KEY_MODE;
101
+ context = argv[2];
102
+ } else {
103
+ fprintf(stderr, "Unknown flag.\n");
104
+ return 1;
105
+ }
106
+ argc -= 2;
107
+ argv += 2;
108
+ }
109
+
110
+ /*
111
+ * We're going to hash the input multiple times, so we need to buffer it all.
112
+ * This is just for test cases, so go ahead and assume that the input is less
113
+ * than 1 MiB.
114
+ */
115
+ size_t buf_capacity = 1 << 20;
116
+ uint8_t *buf = malloc(buf_capacity);
117
+ assert(buf != NULL);
118
+ size_t buf_len = 0;
119
+ while (1) {
120
+ size_t n = fread(&buf[buf_len], 1, buf_capacity - buf_len, stdin);
121
+ if (n == 0) {
122
+ break;
123
+ }
124
+ buf_len += n;
125
+ assert(buf_len < buf_capacity);
126
+ }
127
+
128
+ const int mask = get_cpu_features();
129
+ int feature = 0;
130
+ do {
131
+ fprintf(stderr, "Testing 0x%08X\n", feature);
132
+ g_cpu_features = feature;
133
+ blake3_hasher hasher;
134
+ switch (mode) {
135
+ case HASH_MODE:
136
+ blake3_hasher_init(&hasher);
137
+ break;
138
+ case KEYED_HASH_MODE:
139
+ blake3_hasher_init_keyed(&hasher, key);
140
+ break;
141
+ case DERIVE_KEY_MODE:
142
+ blake3_hasher_init_derive_key(&hasher, context);
143
+ break;
144
+ default:
145
+ abort();
146
+ }
147
+
148
+ blake3_hasher_update(&hasher, buf, buf_len);
149
+
150
+ /* TODO: An incremental output reader API to avoid this allocation. */
151
+ uint8_t *out = malloc(out_len);
152
+ if (out_len > 0 && out == NULL) {
153
+ fprintf(stderr, "malloc() failed.\n");
154
+ return 1;
155
+ }
156
+ blake3_hasher_finalize(&hasher, out, out_len);
157
+ for (size_t i = 0; i < out_len; i++) {
158
+ printf("%02x", out[i]);
159
+ }
160
+ printf("\n");
161
+ free(out);
162
+ feature = (feature - mask) & mask;
163
+ } while (feature != 0);
164
+ free(buf);
165
+ return 0;
166
+ }
@@ -0,0 +1,97 @@
1
+ #! /usr/bin/env python3
2
+
3
+ from binascii import hexlify
4
+ import json
5
+ from os import path
6
+ import subprocess
7
+
8
+ HERE = path.dirname(__file__)
9
+ TEST_VECTORS_PATH = path.join(HERE, "..", "test_vectors", "test_vectors.json")
10
+ TEST_VECTORS = json.load(open(TEST_VECTORS_PATH))
11
+
12
+
13
+ def run_blake3(args, input):
14
+ output = subprocess.run([path.join(HERE, "blake3")] + args,
15
+ input=input,
16
+ stdout=subprocess.PIPE,
17
+ check=True)
18
+ return output.stdout.decode().strip()
19
+
20
+
21
+ # Fill the input with a repeating byte pattern. We use a cycle length of 251,
22
+ # because that's the largets prime number less than 256. This makes it unlikely
23
+ # to swapping any two adjacent input blocks or chunks will give the same
24
+ # answer.
25
+ def make_test_input(length):
26
+ i = 0
27
+ buf = bytearray()
28
+ while len(buf) < length:
29
+ buf.append(i)
30
+ i = (i + 1) % 251
31
+ return buf
32
+
33
+
34
+ def main():
35
+ for case in TEST_VECTORS["cases"]:
36
+ input_len = case["input_len"]
37
+ input = make_test_input(input_len)
38
+ hex_key = hexlify(TEST_VECTORS["key"].encode())
39
+ context_string = TEST_VECTORS["context_string"]
40
+ expected_hash_xof = case["hash"]
41
+ expected_hash = expected_hash_xof[:64]
42
+ expected_keyed_hash_xof = case["keyed_hash"]
43
+ expected_keyed_hash = expected_keyed_hash_xof[:64]
44
+ expected_derive_key_xof = case["derive_key"]
45
+ expected_derive_key = expected_derive_key_xof[:64]
46
+
47
+ # Test the default hash.
48
+ test_hash = run_blake3([], input)
49
+ for line in test_hash.splitlines():
50
+ assert expected_hash == line, \
51
+ "hash({}): {} != {}".format(input_len, expected_hash, line)
52
+
53
+ # Test the extended hash.
54
+ xof_len = len(expected_hash_xof) // 2
55
+ test_hash_xof = run_blake3(["--length", str(xof_len)], input)
56
+ for line in test_hash_xof.splitlines():
57
+ assert expected_hash_xof == line, \
58
+ "hash_xof({}): {} != {}".format(
59
+ input_len, expected_hash_xof, line)
60
+
61
+ # Test the default keyed hash.
62
+ test_keyed_hash = run_blake3(["--keyed", hex_key], input)
63
+ for line in test_keyed_hash.splitlines():
64
+ assert expected_keyed_hash == line, \
65
+ "keyed_hash({}): {} != {}".format(
66
+ input_len, expected_keyed_hash, line)
67
+
68
+ # Test the extended keyed hash.
69
+ xof_len = len(expected_keyed_hash_xof) // 2
70
+ test_keyed_hash_xof = run_blake3(
71
+ ["--keyed", hex_key, "--length",
72
+ str(xof_len)], input)
73
+ for line in test_keyed_hash_xof.splitlines():
74
+ assert expected_keyed_hash_xof == line, \
75
+ "keyed_hash_xof({}): {} != {}".format(
76
+ input_len, expected_keyed_hash_xof, line)
77
+
78
+ # Test the default derive key.
79
+ test_derive_key = run_blake3(["--derive-key", context_string], input)
80
+ for line in test_derive_key.splitlines():
81
+ assert expected_derive_key == line, \
82
+ "derive_key({}): {} != {}".format(
83
+ input_len, expected_derive_key, line)
84
+
85
+ # Test the extended derive key.
86
+ xof_len = len(expected_derive_key_xof) // 2
87
+ test_derive_key_xof = run_blake3(
88
+ ["--derive-key", context_string, "--length",
89
+ str(xof_len)], input)
90
+ for line in test_derive_key_xof.splitlines():
91
+ assert expected_derive_key_xof == line, \
92
+ "derive_key_xof({}): {} != {}".format(
93
+ input_len, expected_derive_key_xof, line)
94
+
95
+
96
+ if __name__ == "__main__":
97
+ main()
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'build/loader'
4
+
5
+ module UncleBlake3
6
+ module Binding
7
+ extend ::FFI::Library
8
+ ffi_lib Build::Loader.find('UncleBlake3')
9
+
10
+ attach_function :key_length, :UncleBlake3_KEY_LEN, %i[], :uint16
11
+ attach_function :default_output_length, :UncleBlake3_OUT_LEN, %i[], :uint16
12
+
13
+ attach_function :init, :UncleBlake3_Init, %i[], :pointer
14
+ attach_function :init_with_key, :UncleBlake3_InitWithKey, %i[pointer], :pointer
15
+ attach_function :init_with_key_seed, :UncleBlake3_InitWithKeySeed, %i[pointer size_t], :pointer
16
+ attach_function :update, :UncleBlake3_Update, %i[pointer pointer size_t], :int
17
+ attach_function :final, :UncleBlake3_Final, %i[pointer pointer size_t], :int
18
+ attach_function :destroy, :UncleBlake3_Destroy, %i[pointer], :void
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require 'pathname'
5
+ require_relative 'platform'
6
+
7
+ module UncleBlake3
8
+ module Build
9
+ # taken from:
10
+ # https://github.com/ffi/ffi-compiler/blob/master/lib/ffi-compiler/loader.rb
11
+ module Loader
12
+ def self.find(name, start_path = nil)
13
+ library = Platform.instance.map_library_name(name)
14
+ root = false
15
+ ::Pathname.new(start_path || caller_path(caller[0])).ascend do |path|
16
+ Dir.glob("#{path}/**/{#{::FFI::Platform::ARCH}-#{::FFI::Platform::OS}/#{library},#{library}}") do |f|
17
+ return f
18
+ end
19
+
20
+ break if root
21
+
22
+ # Next iteration will be the root of the gem if this is the lib/ dir - stop after that
23
+ root = ::File.basename(path) == 'lib'
24
+ end
25
+ raise ::LoadError, "cannot find '#{name}' library"
26
+ end
27
+
28
+ def self.caller_path(line = caller[0])
29
+ if ::FFI::Platform::OS == 'windows'
30
+ drive = line[0..1]
31
+ path = line[2..].split(/:/)[0]
32
+ full_path = drive + path
33
+ else
34
+ full_path = line.split(/:/)[0]
35
+ end
36
+ ::File.dirname full_path
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require 'singleton'
5
+
6
+ module UncleBlake3
7
+ module Build
8
+ # mostly taken from:
9
+ # https://github.com/ffi/ffi-compiler/blob/master/lib/ffi-compiler/platform.rb
10
+
11
+ class Platform
12
+ include ::Singleton
13
+
14
+ LIBSUFFIX = ::FFI::Platform.mac? ? 'bundle' : ::FFI::Platform::LIBSUFFIX
15
+
16
+ def map_library_name(name)
17
+ "#{::FFI::Platform::LIBPREFIX}#{name}.#{LIBSUFFIX}"
18
+ end
19
+
20
+ def arch
21
+ ::FFI::Platform::ARCH
22
+ end
23
+
24
+ def os
25
+ ::FFI::Platform::OS
26
+ end
27
+
28
+ def name
29
+ ::FFI::Platform.name
30
+ end
31
+
32
+ def mac?
33
+ ::FFI::Platform.mac?
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './build/platform'
4
+ require_relative './build/loader'
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'ffi'
5
+ require 'objspace'
6
+ require_relative 'binding'
7
+
8
+ module UncleBlake3
9
+ class Digest
10
+ KEY_LENGTH = Binding.key_length
11
+ DEFAULT_OUTPUT_LENGTH = Binding.default_output_length
12
+
13
+ module Error
14
+ end
15
+
16
+ class ArgumentError < ::ArgumentError
17
+ include Error
18
+ end
19
+
20
+ class TypeError < ::TypeError
21
+ include Error
22
+ end
23
+
24
+ def initialize(output_length: DEFAULT_OUTPUT_LENGTH, key: nil, key_seed: nil)
25
+ raise TypeError, 'Hash length is not an Integer' unless output_length.is_a?(::Integer)
26
+ raise ArgumentError, 'Hash length out of range' unless (1...(1 << 20)).include?(output_length)
27
+ raise TypeError, 'Key is not a String' if !key.nil? && !key.is_a?(::String)
28
+ raise ArgumentError, 'Key length mismatched' unless key.nil? || (key.bytesize == KEY_LENGTH)
29
+ raise TypeError, 'Key seed is not a String' if !key_seed.nil? && !key_seed.is_a?(::String)
30
+ @native_instance = if !key && !key_seed
31
+ Binding.init
32
+ elsif key && key_seed
33
+ raise ::ArgumentError, 'Both key and key_seed available at the same time; please pick only one.'
34
+ elsif key
35
+ key_buffer = ::FFI::MemoryPointer.new(:uint8, KEY_LENGTH)
36
+ key_buffer.put_bytes(0, key)
37
+ Binding.init_with_key(key_buffer)
38
+ elsif key_seed
39
+ seed_size = key_seed.bytesize
40
+ seed_buffer = ::FFI::MemoryPointer.new(:uint8, seed_size)
41
+ seed_buffer.put_bytes(0, key_seed)
42
+ Binding.init_with_key_seed(seed_buffer, seed_size)
43
+ else
44
+ raise ::ArgumentError, 'Unknown mode of operation'
45
+ end.tap do |pointer|
46
+ ::ObjectSpace.define_finalizer(self, self.class._create_finalizer(pointer))
47
+ end
48
+ @output_length = output_length
49
+ invalidate_cache
50
+ end
51
+
52
+ def update(data)
53
+ data_size = data.bytesize
54
+ data_buffer = ::FFI::MemoryPointer.new(:uint8, data_size)
55
+ data_buffer.put_bytes(0, data)
56
+ Binding.update(@native_instance, data_buffer, data_size)
57
+ self
58
+ ensure
59
+ invalidate_cache
60
+ end
61
+
62
+ def <<(*args, **kwargs)
63
+ update(*args, **kwargs)
64
+ end
65
+
66
+ def digest
67
+ @_digest_cache ||= begin
68
+ data_buffer = ::FFI::MemoryPointer.new(:uint8, @output_length)
69
+ Binding.final(@native_instance, data_buffer, @output_length)
70
+ data_buffer.get_bytes(0, @output_length)
71
+ end
72
+ end
73
+
74
+ def hexdigest
75
+ @_hexdigest_cache ||= digest.unpack1('H*')
76
+ end
77
+
78
+ def base64digest
79
+ @_base64digest_cache ||= ::Base64.strict_encode64(digest)
80
+ end
81
+
82
+ private
83
+
84
+ def invalidate_cache
85
+ @_digest_cache = nil
86
+ @_hexdigest_cache = nil
87
+ @_base64digest_cache = nil
88
+ end
89
+
90
+ class << self
91
+ # https://www.mikeperham.com/2010/02/24/the-trouble-with-ruby-finalizers/
92
+ def _create_finalizer(instance)
93
+ proc {
94
+ Binding.destroy(instance)
95
+ }
96
+ end
97
+
98
+ def digest(*args, **kwargs)
99
+ _generic_digest(*args, **kwargs, &:digest)
100
+ end
101
+
102
+ def hexdigest(*args, **kwargs)
103
+ _generic_digest(*args, **kwargs, &:hexdigest)
104
+ end
105
+
106
+ def base64digest(*args, **kwargs)
107
+ _generic_digest(*args, **kwargs, &:base64digest)
108
+ end
109
+
110
+ private
111
+
112
+ def _generic_digest(data, output_length: nil, key: nil, key_seed: nil, &hash_finalizer)
113
+ instance = new(**{ output_length: output_length, key: key, key_seed: key_seed }.compact)
114
+ instance.update(data)
115
+ hash_finalizer.call(instance)
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UncleBlake3
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'uncle_blake3/version'
4
+ require_relative 'uncle_blake3/digest'
5
+
6
+ module UncleBlake3
7
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: uncle_blake3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sarun Rattanasiri
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-02-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.15.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.15.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 13.0.6
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 13.0.6
41
+ description: This gem brought the hash algorithm, Blake3, to Ruby. It uses the official
42
+ Blake3 implementation which optimized and maintained by the original Blake3 team
43
+ themselves.
44
+ email: midnight_w@gmx.tw
45
+ executables: []
46
+ extensions:
47
+ - ext/Rakefile
48
+ extra_rdoc_files: []
49
+ files:
50
+ - LICENSE.md
51
+ - README.md
52
+ - ext/Rakefile
53
+ - ext/binding/uncle_blake3.c
54
+ - ext/blake3/c/Makefile.testing
55
+ - ext/blake3/c/README.md
56
+ - ext/blake3/c/blake3.c
57
+ - ext/blake3/c/blake3.h
58
+ - ext/blake3/c/blake3_avx2.c
59
+ - ext/blake3/c/blake3_avx2_x86-64_unix.S
60
+ - ext/blake3/c/blake3_avx2_x86-64_windows_gnu.S
61
+ - ext/blake3/c/blake3_avx2_x86-64_windows_msvc.asm
62
+ - ext/blake3/c/blake3_avx512.c
63
+ - ext/blake3/c/blake3_avx512_x86-64_unix.S
64
+ - ext/blake3/c/blake3_avx512_x86-64_windows_gnu.S
65
+ - ext/blake3/c/blake3_avx512_x86-64_windows_msvc.asm
66
+ - ext/blake3/c/blake3_dispatch.c
67
+ - ext/blake3/c/blake3_impl.h
68
+ - ext/blake3/c/blake3_neon.c
69
+ - ext/blake3/c/blake3_portable.c
70
+ - ext/blake3/c/blake3_sse2.c
71
+ - ext/blake3/c/blake3_sse2_x86-64_unix.S
72
+ - ext/blake3/c/blake3_sse2_x86-64_windows_gnu.S
73
+ - ext/blake3/c/blake3_sse2_x86-64_windows_msvc.asm
74
+ - ext/blake3/c/blake3_sse41.c
75
+ - ext/blake3/c/blake3_sse41_x86-64_unix.S
76
+ - ext/blake3/c/blake3_sse41_x86-64_windows_gnu.S
77
+ - ext/blake3/c/blake3_sse41_x86-64_windows_msvc.asm
78
+ - ext/blake3/c/example.c
79
+ - ext/blake3/c/main.c
80
+ - ext/blake3/c/test.py
81
+ - lib/uncle_blake3.rb
82
+ - lib/uncle_blake3/binding.rb
83
+ - lib/uncle_blake3/build.rb
84
+ - lib/uncle_blake3/build/loader.rb
85
+ - lib/uncle_blake3/build/platform.rb
86
+ - lib/uncle_blake3/digest.rb
87
+ - lib/uncle_blake3/version.rb
88
+ homepage: https://github.com/the-cave/uncle-blake3
89
+ licenses: []
90
+ metadata:
91
+ homepage_uri: https://github.com/the-cave/uncle-blake3
92
+ source_code_uri: https://github.com/the-cave/uncle-blake3/tree/v0.0.1
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: 2.6.0
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.2.32
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: A binding of the Blake3 hash algorithm for Ruby
112
+ test_files: []