scale_rb 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.
- 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: []
|