scale_rb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.txt +21 -0
- data/README.md +42 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/metadata +41 -0
- data/bin/setup +8 -0
- data/lib/client/client.rb +76 -0
- data/lib/client/rpc.rb +60 -0
- data/lib/codec.rb +387 -0
- data/lib/hasher.rb +54 -0
- data/lib/metadata.rb +199 -0
- data/lib/metadata_v14.rb +21 -0
- data/lib/monkey_patching.rb +113 -0
- data/lib/portable_codec.rb +251 -0
- data/lib/registry.rb +13 -0
- data/lib/scale_rb/version.rb +3 -0
- data/lib/scale_rb.rb +39 -0
- data/lib/storage_helper.rb +38 -0
- data/scale_rb.gemspec +31 -0
- metadata +99 -0
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# https://www.rubyguides.com/2017/01/read-binary-data/
|
4
|
+
class String
|
5
|
+
def to_bytes
|
6
|
+
data = start_with?('0x') ? self[2..] : self
|
7
|
+
raise 'Not valid hex string' if data =~ /[^\da-f]+/i
|
8
|
+
|
9
|
+
data = "0#{data}" if data.length.odd?
|
10
|
+
data.scan(/../).map(&:hex)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_camel
|
14
|
+
split('_').collect(&:capitalize).join
|
15
|
+
end
|
16
|
+
|
17
|
+
def underscore
|
18
|
+
gsub(/::/, '/')
|
19
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
20
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
21
|
+
.tr('-', '_')
|
22
|
+
.downcase
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Integer
|
27
|
+
def to_bytes(bit_length = nil)
|
28
|
+
return to_s(16).to_bytes unless bit_length
|
29
|
+
|
30
|
+
hex = to_s(16).rjust(bit_length / 4, '0')
|
31
|
+
hex.to_bytes
|
32
|
+
end
|
33
|
+
|
34
|
+
# unsigned to signed
|
35
|
+
def to_signed(bit_length)
|
36
|
+
unsigned_mid = 2**(bit_length - 1)
|
37
|
+
unsigned_ceiling = 2**bit_length
|
38
|
+
self >= unsigned_mid ? self - unsigned_ceiling : self
|
39
|
+
end
|
40
|
+
|
41
|
+
# signed to unsigned
|
42
|
+
def to_unsigned(bit_length)
|
43
|
+
unsigned_mid = 2**(bit_length - 1)
|
44
|
+
unsigned_ceiling = 2**bit_length
|
45
|
+
raise 'out of scope' if self >= unsigned_mid || self <= -unsigned_mid
|
46
|
+
|
47
|
+
negative? ? unsigned_ceiling + self : self
|
48
|
+
end
|
49
|
+
|
50
|
+
# unix timestamp to utc
|
51
|
+
def to_utc
|
52
|
+
Time.at(self).utc.asctime
|
53
|
+
end
|
54
|
+
|
55
|
+
# utc to unix timestamp
|
56
|
+
def from_utc(utc_asctime)
|
57
|
+
Time.parse(utc_asctime)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Array
|
62
|
+
def to_hex
|
63
|
+
raise 'Not a byte array' unless byte_array?
|
64
|
+
|
65
|
+
reduce('0x') { |hex, byte| hex + byte.to_s(16).rjust(2, '0') }
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_bin
|
69
|
+
raise 'Not a byte array' unless byte_array?
|
70
|
+
|
71
|
+
reduce('0b') { |bin, byte| bin + byte.to_s(2).rjust(8, '0') }
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_utf8
|
75
|
+
raise 'Not a byte array' unless byte_array?
|
76
|
+
|
77
|
+
pack('C*').force_encoding('utf-8')
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_uint
|
81
|
+
to_hex.to_i(16)
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_int(bit_length)
|
85
|
+
to_uint.to_signed(bit_length)
|
86
|
+
end
|
87
|
+
|
88
|
+
def flip
|
89
|
+
reverse
|
90
|
+
end
|
91
|
+
|
92
|
+
def byte_array?
|
93
|
+
all? { |e| e >= 0 and e <= 255 }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Hash
|
98
|
+
def _key?(key)
|
99
|
+
if key.instance_of?(String)
|
100
|
+
key?(key) || key?(key.to_sym)
|
101
|
+
else
|
102
|
+
key?(key) || key?(key.to_s)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def _get(key)
|
107
|
+
if key.instance_of?(String)
|
108
|
+
self[key] || self[key.to_sym]
|
109
|
+
else
|
110
|
+
self[key] || self[key.to_s]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PortableCodec
|
4
|
+
class Error < StandardError; end
|
5
|
+
class TypeNotFound < Error; end
|
6
|
+
class TypeNotImplemented < Error; end
|
7
|
+
class CompositeInvalidValue < Error; end
|
8
|
+
class ArrayLengthNotEqual < Error; end
|
9
|
+
class VariantItemNotFound < Error; end
|
10
|
+
class VariantIndexOutOfRange < Error; end
|
11
|
+
class VariantInvalidValue < Error; end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# registry:
|
15
|
+
# {
|
16
|
+
# 0 => {
|
17
|
+
# path: [...],
|
18
|
+
# params: [...],
|
19
|
+
# def: {
|
20
|
+
# primitive: 'u8' | array: {} | ...
|
21
|
+
# }
|
22
|
+
# },
|
23
|
+
# 1 => {
|
24
|
+
# ...
|
25
|
+
# }
|
26
|
+
# }
|
27
|
+
def decode(id, bytes, registry)
|
28
|
+
type = registry[id]
|
29
|
+
raise TypeNotFound, "id: #{id}" if type.nil?
|
30
|
+
|
31
|
+
_path = type._get(:path)
|
32
|
+
_params = type._get(:params)
|
33
|
+
type_def = type._get(:def)
|
34
|
+
|
35
|
+
return decode_primitive(type_def, bytes) if type_def._key?(:primitive)
|
36
|
+
return decode_compact(bytes) if type_def._key?(:compact)
|
37
|
+
return decode_array(type_def._get(:array), bytes, registry) if type_def._key?(:array)
|
38
|
+
return decode_sequence(type_def._get(:sequence), bytes, registry) if type_def._key?(:sequence)
|
39
|
+
return decode_tuple(type_def._get(:tuple), bytes, registry) if type_def._key?(:tuple)
|
40
|
+
return decode_composite(type_def._get(:composite), bytes, registry) if type_def._key?(:composite)
|
41
|
+
return decode_variant(type_def._get(:variant), bytes, registry) if type_def._key?(:variant)
|
42
|
+
|
43
|
+
raise TypeNotImplemented, "id: #{id}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Uint, Str, Bool
|
47
|
+
# Int, Bytes ?
|
48
|
+
def decode_primitive(type_def, bytes)
|
49
|
+
primitive = type_def._get(:primitive)
|
50
|
+
return ScaleRb.decode_uint(primitive, bytes) if uint?(primitive)
|
51
|
+
return ScaleRb.decode_string(bytes) if string?(primitive)
|
52
|
+
return ScaleRb.decode_boolean(bytes) if boolean?(primitive)
|
53
|
+
# return ScaleRb.decode_int(primitive, bytes) if int?(primitive)
|
54
|
+
# return ScaleRb.decode_bytes(bytes) if bytes?(primitive)
|
55
|
+
end
|
56
|
+
|
57
|
+
def decode_compact(bytes)
|
58
|
+
ScaleRb.decode_compact(bytes)
|
59
|
+
end
|
60
|
+
|
61
|
+
def decode_array(array_type, bytes, registry)
|
62
|
+
len = array_type._get(:len)
|
63
|
+
inner_type_id = array_type._get(:type)
|
64
|
+
_decode_types([inner_type_id] * len, bytes, registry)
|
65
|
+
end
|
66
|
+
|
67
|
+
def decode_sequence(sequence_type, bytes, registry)
|
68
|
+
len, remaining_bytes = decode_compact(bytes)
|
69
|
+
inner_type_id = sequence_type._get(:type)
|
70
|
+
_decode_types([inner_type_id] * len, remaining_bytes, registry)
|
71
|
+
end
|
72
|
+
|
73
|
+
def decode_tuple(tuple_type, bytes, registry)
|
74
|
+
_decode_types(tuple_type, bytes, registry)
|
75
|
+
end
|
76
|
+
|
77
|
+
# {
|
78
|
+
# name: value,
|
79
|
+
# ...
|
80
|
+
# }
|
81
|
+
def decode_composite(composite_type, bytes, registry)
|
82
|
+
fields = composite_type._get(:fields)
|
83
|
+
|
84
|
+
type_name_list = fields.map { |f| f._get(:name) }
|
85
|
+
type_id_list = fields.map { |f| f._get(:type) }
|
86
|
+
|
87
|
+
type_value_list, remaining_bytes = _decode_types(type_id_list, bytes, registry)
|
88
|
+
[
|
89
|
+
if type_name_list.all?(&:nil?)
|
90
|
+
type_value_list
|
91
|
+
else
|
92
|
+
[type_name_list.map(&:to_sym), type_value_list].transpose.to_h
|
93
|
+
end,
|
94
|
+
remaining_bytes
|
95
|
+
]
|
96
|
+
end
|
97
|
+
|
98
|
+
def decode_variant(variant_type, bytes, registry)
|
99
|
+
variants = variant_type._get(:variants)
|
100
|
+
|
101
|
+
index = bytes[0]
|
102
|
+
if index > (variants.length - 1)
|
103
|
+
raise VariantIndexOutOfRange,
|
104
|
+
"type: #{variant_type}, index: #{index}, bytes: #{bytes}"
|
105
|
+
end
|
106
|
+
|
107
|
+
item_variant = variants.find { |v| v._get(:index) == index }
|
108
|
+
item_name = item_variant._get(:name)
|
109
|
+
item, remaining_bytes = decode_composite(item_variant, bytes[1..], registry)
|
110
|
+
|
111
|
+
[
|
112
|
+
item.empty? ? item_name : { item_name.to_sym => item },
|
113
|
+
remaining_bytes
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
def _decode_types(ids, bytes, registry = {})
|
118
|
+
if ids.empty?
|
119
|
+
[[], bytes]
|
120
|
+
else
|
121
|
+
value, remaining_bytes = decode(ids.first, bytes, registry)
|
122
|
+
value_list, remaining_bytes = _decode_types(ids[1..], remaining_bytes, registry)
|
123
|
+
[[value] + value_list, remaining_bytes]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def encode_with_hasher(value, type_id, registry, hasher)
|
128
|
+
value_bytes = encode(type_id, value, registry)
|
129
|
+
Hasher.apply_hasher(hasher, value_bytes)
|
130
|
+
end
|
131
|
+
|
132
|
+
def encode(id, value, registry)
|
133
|
+
type = registry[id]
|
134
|
+
raise TypeNotFound, "id: #{id}" if type.nil?
|
135
|
+
|
136
|
+
type_def = type._get(:def)
|
137
|
+
|
138
|
+
return encode_primitive(type_def, value) if type_def._key?(:primitive)
|
139
|
+
return encode_compact(value) if type_def._key?(:compact)
|
140
|
+
return encode_array(type_def._get(:array), value, registry) if type_def._key?(:array)
|
141
|
+
return encode_sequence(type_def._get(:sequence), value, registry) if type_def._key?(:sequence)
|
142
|
+
return encode_tuple(type_def._get(:tuple), value, registry) if type_def._key?(:tuple)
|
143
|
+
return encode_composite(type_def._get(:composite), value, registry) if type_def._key?(:composite)
|
144
|
+
return encode_variant(type_def._get(:variant), value, registry) if type_def._key?(:variant)
|
145
|
+
|
146
|
+
raise TypeNotImplemented, "id: #{id}"
|
147
|
+
end
|
148
|
+
|
149
|
+
def encode_primitive(type_def, value)
|
150
|
+
primitive = type_def._get(:primitive)
|
151
|
+
return ScaleRb.encode_uint(primitive, value) if uint?(primitive)
|
152
|
+
return ScaleRb.encode_string(value) if string?(primitive)
|
153
|
+
return ScaleRb.encode_boolean(value) if boolean?(primitive)
|
154
|
+
end
|
155
|
+
|
156
|
+
def encode_compact(value)
|
157
|
+
ScaleRb.encode_compact(value)
|
158
|
+
end
|
159
|
+
|
160
|
+
def encode_array(array_type, value, registry)
|
161
|
+
length = array_type._get(:len)
|
162
|
+
inner_type_id = array_type._get(:type)
|
163
|
+
raise ArrayLengthNotEqual, "type: #{array_type}, value: #{value.inspect}" if length != value.length
|
164
|
+
|
165
|
+
_encode_types([inner_type_id] * length, value, registry)
|
166
|
+
end
|
167
|
+
|
168
|
+
def encode_sequence(sequence_type, value, registry)
|
169
|
+
inner_type_id = sequence_type._get(:type)
|
170
|
+
length_bytes = encode_compact(value.length)
|
171
|
+
length_bytes + _encode_types([inner_type_id] * array.length, value, registry)
|
172
|
+
end
|
173
|
+
|
174
|
+
# tuple_type: [type_id1, type_id2, ...]
|
175
|
+
def encode_tuple(tuple_type, value, registry)
|
176
|
+
_encode_types(tuple_type, value, registry)
|
177
|
+
end
|
178
|
+
|
179
|
+
# value:
|
180
|
+
# {
|
181
|
+
# name1: value1,
|
182
|
+
# name2: value2,
|
183
|
+
# ...
|
184
|
+
# }
|
185
|
+
# or
|
186
|
+
# [value1, value2, ...]
|
187
|
+
def encode_composite(composite_type, value, registry)
|
188
|
+
values =
|
189
|
+
if value.instance_of?(Hash)
|
190
|
+
value.values
|
191
|
+
elsif value.instance_of?(Array)
|
192
|
+
value
|
193
|
+
else
|
194
|
+
raise CompositeInvalidValue, "value: #{value}, only hash and array"
|
195
|
+
end
|
196
|
+
|
197
|
+
fields = composite_type._get(:fields)
|
198
|
+
type_id_list = fields.map { |f| f._get(:type) }
|
199
|
+
_encode_types(type_id_list, values, registry)
|
200
|
+
end
|
201
|
+
|
202
|
+
# value:
|
203
|
+
# {
|
204
|
+
# name: the_value(Hash)
|
205
|
+
# }
|
206
|
+
# or
|
207
|
+
# the_value(String)
|
208
|
+
def encode_variant(variant_type, value, registry)
|
209
|
+
variants = variant_type._get(:variants)
|
210
|
+
|
211
|
+
if value.instance_of?(Hash)
|
212
|
+
name = value.keys.first.to_s
|
213
|
+
the_value = value.values.first
|
214
|
+
elsif value.instance_of?(String)
|
215
|
+
name = value
|
216
|
+
the_value = {}
|
217
|
+
else
|
218
|
+
raise VariantInvalidValue, "type: #{variant_type}, value: #{value}"
|
219
|
+
end
|
220
|
+
|
221
|
+
variant = variants.find { |v| v[:name] == name }
|
222
|
+
raise VariantItemNotFound, "type: #{variant_type}, name: #{name}" if variant.nil?
|
223
|
+
|
224
|
+
ScaleRb.encode_uint('u8', variant._get(:index)) + encode_composite(variant, the_value, registry)
|
225
|
+
end
|
226
|
+
|
227
|
+
def _encode_types(ids, values, registry)
|
228
|
+
_encode_types_without_merge(ids, values, registry).flatten
|
229
|
+
end
|
230
|
+
|
231
|
+
def _encode_types_with_hashers(values, type_ids, registry, hashers)
|
232
|
+
if !hashers.nil? && hashers.length != type_ids.length
|
233
|
+
raise ScaleRb::LengthNotEqualErr, "type_ids length: #{type_ids.length}, hashers length: #{hashers.length}"
|
234
|
+
end
|
235
|
+
|
236
|
+
bytes_array = _encode_types_without_merge(type_ids, values, registry)
|
237
|
+
bytes_array.each_with_index.reduce([]) do |memo, (bytes, i)|
|
238
|
+
memo + Hasher.apply_hasher(hashers[i], bytes)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# return: [value1_bytes, value2_bytes, ...]
|
243
|
+
def _encode_types_without_merge(ids, values, registry)
|
244
|
+
raise ScaleRb::LengthNotEqualErr, "types: #{ids}, values: #{values.inspect}" if ids.length != values.length
|
245
|
+
|
246
|
+
ids.map.with_index do |type_id, i|
|
247
|
+
encode(type_id, values[i], registry)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
data/lib/registry.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ScaleRb
|
4
|
+
# A `registry` is a ruby Hash object, key is the type name, value is the type definition or mapped type name.
|
5
|
+
# A `config` contains the complete versioned type definition for a network.
|
6
|
+
# https://github.com/polkadot-js/api/blob/master/packages/types-known/src/spec/polkadot.ts
|
7
|
+
def self.build_registry_from_config(config, spec_version)
|
8
|
+
version = config[:versioned].find do |item|
|
9
|
+
item[:minmax].include?(spec_version)
|
10
|
+
end
|
11
|
+
config[:shared_types].merge(version.nil? ? {} : version[:types])
|
12
|
+
end
|
13
|
+
end
|
data/lib/scale_rb.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'scale_rb/version'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# scale codec
|
7
|
+
require 'monkey_patching'
|
8
|
+
require 'codec'
|
9
|
+
require 'portable_codec'
|
10
|
+
|
11
|
+
# metadata types, decoding and helpers
|
12
|
+
require 'metadata'
|
13
|
+
require 'metadata_v14'
|
14
|
+
|
15
|
+
require 'hasher'
|
16
|
+
require 'storage_helper'
|
17
|
+
|
18
|
+
# client
|
19
|
+
require 'client/rpc'
|
20
|
+
require 'client/client'
|
21
|
+
|
22
|
+
# get registry from config
|
23
|
+
require 'registry'
|
24
|
+
|
25
|
+
module ScaleRb
|
26
|
+
class << self
|
27
|
+
attr_writer :logger
|
28
|
+
|
29
|
+
def logger
|
30
|
+
@logger ||= Logger.new($stdout)
|
31
|
+
@logger.level = Logger::INFO
|
32
|
+
@logger
|
33
|
+
end
|
34
|
+
|
35
|
+
def debug(key, value)
|
36
|
+
logger.debug "#{key.rjust(15)}: #{value}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StorageHelper
|
4
|
+
class << self
|
5
|
+
# params:
|
6
|
+
# pallet_name: module name
|
7
|
+
# method_name: storage name
|
8
|
+
# params: {
|
9
|
+
# values: values,
|
10
|
+
# type_ids: type_ids,
|
11
|
+
# hashers: hashers,
|
12
|
+
# }
|
13
|
+
# registry: portable_types_registry
|
14
|
+
def encode_storage_key(pallet_name, method_name, params = nil, registry = nil)
|
15
|
+
pallet_method_key = Hasher.twox128(pallet_name) + Hasher.twox128(method_name)
|
16
|
+
|
17
|
+
if params.nil?
|
18
|
+
pallet_method_key
|
19
|
+
else
|
20
|
+
values = params[:values]
|
21
|
+
type_ids = params[:type_ids]
|
22
|
+
hashers = params[:hashers]
|
23
|
+
|
24
|
+
pallet_method_key + PortableCodec._encode_types_with_hashers(values, type_ids, registry, hashers)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_params(param_values, storage_key_type_id, hashers, registry)
|
29
|
+
type_ids = registry._get(storage_key_type_id)._get(:def)._get(:tuple)
|
30
|
+
type_ids = [storage_key_type_id] if type_ids.nil?
|
31
|
+
{
|
32
|
+
values: param_values,
|
33
|
+
type_ids: type_ids,
|
34
|
+
hashers: hashers
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/scale_rb.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'lib/scale_rb/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'scale_rb'
|
5
|
+
spec.version = ScaleRb::VERSION
|
6
|
+
spec.authors = ['Aki Wu']
|
7
|
+
spec.email = ['wuminzhe@gmail.com']
|
8
|
+
|
9
|
+
spec.summary = 'New Ruby SCALE Codec Library'
|
10
|
+
spec.description = 'Ruby implementation of the parity SCALE data format'
|
11
|
+
spec.homepage = 'https://github.com/wuminzhe/scale_rb'
|
12
|
+
spec.license = 'MIT'
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0')
|
14
|
+
|
15
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
16
|
+
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = 'exe'
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ['lib']
|
27
|
+
|
28
|
+
# for hashers
|
29
|
+
spec.add_dependency 'blake2b_rs', '~> 0.1.2'
|
30
|
+
spec.add_dependency 'xxhash'
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scale_rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aki Wu
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-10-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: blake2b_rs
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: xxhash
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Ruby implementation of the parity SCALE data format
|
42
|
+
email:
|
43
|
+
- wuminzhe@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- ".rspec"
|
50
|
+
- ".rubocop.yml"
|
51
|
+
- ".travis.yml"
|
52
|
+
- CODE_OF_CONDUCT.md
|
53
|
+
- Gemfile
|
54
|
+
- Gemfile.lock
|
55
|
+
- LICENSE.txt
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- bin/console
|
59
|
+
- bin/metadata
|
60
|
+
- bin/setup
|
61
|
+
- lib/client/client.rb
|
62
|
+
- lib/client/rpc.rb
|
63
|
+
- lib/codec.rb
|
64
|
+
- lib/hasher.rb
|
65
|
+
- lib/metadata.rb
|
66
|
+
- lib/metadata_v14.rb
|
67
|
+
- lib/monkey_patching.rb
|
68
|
+
- lib/portable_codec.rb
|
69
|
+
- lib/registry.rb
|
70
|
+
- lib/scale_rb.rb
|
71
|
+
- lib/scale_rb/version.rb
|
72
|
+
- lib/storage_helper.rb
|
73
|
+
- scale_rb.gemspec
|
74
|
+
homepage: https://github.com/wuminzhe/scale_rb
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata:
|
78
|
+
allowed_push_host: https://rubygems.org
|
79
|
+
homepage_uri: https://github.com/wuminzhe/scale_rb
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.6.0
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubygems_version: 3.1.4
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: New Ruby SCALE Codec Library
|
99
|
+
test_files: []
|