scale_rb 0.4.1 → 0.5.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 +4 -4
- data/.devcontainer/devcontainer.json +21 -0
- data/Dockerfile +16 -0
- data/Gemfile +4 -4
- data/README.md +19 -6
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/examples/http_client_1.rb +0 -2
- data/examples/http_client_2.rb +0 -2
- data/examples/ws_client_1.rb +0 -2
- data/examples/ws_client_3.rb +1 -3
- data/examples/ws_client_4.rb +0 -2
- data/exe/metadata +9 -11
- data/lib/address.rb +1 -1
- data/lib/custom_assign.rb +92 -0
- data/lib/scale_rb/call_helper.rb +42 -0
- data/lib/{client → scale_rb/client}/client_ext.rb +12 -13
- data/lib/{client → scale_rb/client}/http_client.rb +3 -5
- data/lib/{client → scale_rb/client}/ws_client.rb +13 -20
- data/lib/scale_rb/codec.rb +25 -0
- data/lib/scale_rb/codec_utils.rb +128 -0
- data/lib/scale_rb/decode.rb +164 -0
- data/lib/scale_rb/encode.rb +150 -0
- data/lib/{hasher.rb → scale_rb/hasher.rb} +10 -8
- data/lib/scale_rb/metadata/metadata.rb +114 -0
- data/lib/{metadata → scale_rb/metadata}/metadata_v10.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v11.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v12.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v13.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v14.rb +18 -18
- data/lib/{metadata → scale_rb/metadata}/metadata_v9.rb +0 -17
- data/lib/scale_rb/metadata/registry.rb +263 -0
- data/lib/scale_rb/metadata/type_exp.rb +286 -0
- data/lib/scale_rb/portable_registry.rb +133 -0
- data/lib/{storage_helper.rb → scale_rb/storage_helper.rb} +16 -4
- data/lib/scale_rb/types.rb +233 -0
- data/lib/scale_rb/utils.rb +125 -0
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +22 -30
- data/lib/type_enforcer.rb +170 -0
- data/scale_rb.gemspec +5 -0
- metadata +71 -19
- data/lib/codec.rb +0 -450
- data/lib/metadata/metadata.rb +0 -137
- data/lib/monkey_patching.rb +0 -115
- data/lib/portable_codec.rb +0 -285
- data/lib/registry.rb +0 -13
data/lib/codec.rb
DELETED
@@ -1,450 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ScaleRb
|
4
|
-
class Error < StandardError; end
|
5
|
-
class NotImplemented < Error; end
|
6
|
-
class NilTypeError < Error; end
|
7
|
-
class TypeParseError < Error; end
|
8
|
-
class NotEnoughBytesError < Error; end
|
9
|
-
class InvalidBytesError < Error; end
|
10
|
-
class Unreachable < Error; end
|
11
|
-
class IndexOutOfRangeError < Error; end
|
12
|
-
class LengthNotEqualErr < Error; end
|
13
|
-
class InvalidValueError < Error; end
|
14
|
-
end
|
15
|
-
|
16
|
-
# TODO: set, bitvec
|
17
|
-
module ScaleRb
|
18
|
-
class << self
|
19
|
-
def type_def?(type)
|
20
|
-
type.instance_of?(String) && (
|
21
|
-
bytes?(type) ||
|
22
|
-
boolean?(type) ||
|
23
|
-
string?(type) ||
|
24
|
-
compact?(type) ||
|
25
|
-
int?(type) ||
|
26
|
-
uint?(type) ||
|
27
|
-
option?(type) ||
|
28
|
-
array?(type) ||
|
29
|
-
vec?(type) ||
|
30
|
-
tuple?(type)
|
31
|
-
) ||
|
32
|
-
type.instance_of?(Hash)
|
33
|
-
end
|
34
|
-
|
35
|
-
def bytes?(type)
|
36
|
-
type.downcase == 'bytes'
|
37
|
-
end
|
38
|
-
|
39
|
-
def boolean?(type)
|
40
|
-
type.downcase == 'bool' || type.downcase == 'boolean'
|
41
|
-
end
|
42
|
-
|
43
|
-
def string?(type)
|
44
|
-
type.downcase == 'str' || type.downcase == 'string' || type.downcase == 'text' || type.downcase == 'type'
|
45
|
-
end
|
46
|
-
|
47
|
-
def compact?(type)
|
48
|
-
type.downcase == 'compact' ||
|
49
|
-
(type[0..7].downcase == 'compact<' && type[-1] == '>')
|
50
|
-
end
|
51
|
-
|
52
|
-
def int?(type)
|
53
|
-
type[0].downcase == 'i' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
|
54
|
-
end
|
55
|
-
|
56
|
-
def uint?(type)
|
57
|
-
type[0].downcase == 'u' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
|
58
|
-
end
|
59
|
-
|
60
|
-
def option?(type)
|
61
|
-
type[0..6].downcase == 'option<' && type[-1] == '>'
|
62
|
-
end
|
63
|
-
|
64
|
-
def array?(type)
|
65
|
-
type[0] == '[' && type[-1] == ']'
|
66
|
-
end
|
67
|
-
|
68
|
-
def vec?(type)
|
69
|
-
type[0..3].downcase == 'vec<' && type[-1] == '>'
|
70
|
-
end
|
71
|
-
|
72
|
-
def tuple?(type)
|
73
|
-
type[0] == '(' && type[-1] == ')'
|
74
|
-
end
|
75
|
-
|
76
|
-
def struct?(type)
|
77
|
-
type.instance_of?(Hash)
|
78
|
-
end
|
79
|
-
|
80
|
-
def enum?(type)
|
81
|
-
type.instance_of?(Hash) && type.key?(:_enum)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
module ScaleRb
|
87
|
-
class << self
|
88
|
-
def parse_option(type)
|
89
|
-
type.scan(/\A[O|o]ption<(.+)>\z/).first.first
|
90
|
-
end
|
91
|
-
|
92
|
-
def parse_array(type)
|
93
|
-
scan_out = type.scan(/\A\[\s*(.+)\s*;\s*(\d+)\s*\]\z/)
|
94
|
-
raise ScaleRb::TypeParseError, type if scan_out.empty?
|
95
|
-
raise ScaleRb::TypeParseError, type if scan_out[0].length != 2
|
96
|
-
|
97
|
-
inner_type = scan_out[0][0]
|
98
|
-
length = scan_out[0][1].to_i
|
99
|
-
[inner_type, length]
|
100
|
-
end
|
101
|
-
|
102
|
-
def parse_vec(type)
|
103
|
-
type.scan(/\A[V|v]ec<(.+)>\z/).first.first
|
104
|
-
end
|
105
|
-
|
106
|
-
def parse_tuple(type)
|
107
|
-
type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Helper functions
|
113
|
-
module ScaleRb
|
114
|
-
class << self
|
115
|
-
def _get_final_type_from_registry(registry, type)
|
116
|
-
raise "Wrong lookup type #{type.class}" if !type.instance_of?(String) && !type.instance_of?(Hash)
|
117
|
-
|
118
|
-
return if type.instance_of?(Hash)
|
119
|
-
|
120
|
-
mapped = registry._get(type) # mapped: String(name, type_def) | Hash(type_def: struct, enum) | nil
|
121
|
-
|
122
|
-
return if mapped.nil?
|
123
|
-
return mapped if type_def?(mapped)
|
124
|
-
|
125
|
-
_get_final_type_from_registry(registry, mapped)
|
126
|
-
end
|
127
|
-
|
128
|
-
def _decode_types(types, bytes, registry)
|
129
|
-
_decode_each(types, bytes) do |type, remaining_bytes|
|
130
|
-
decode(type, remaining_bytes, registry)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def _decode_each(types, bytes, &decode)
|
135
|
-
remaining_bytes = bytes
|
136
|
-
values = types.map do |type|
|
137
|
-
value, remaining_bytes = decode.call(type, remaining_bytes)
|
138
|
-
value
|
139
|
-
end
|
140
|
-
[values, remaining_bytes]
|
141
|
-
end
|
142
|
-
|
143
|
-
def _do_decode_compact(bytes)
|
144
|
-
case bytes[0] & 3
|
145
|
-
when 0
|
146
|
-
[bytes[0] >> 2, bytes[1..]]
|
147
|
-
when 1
|
148
|
-
[bytes[0..1]._flip._to_uint >> 2, bytes[2..]]
|
149
|
-
when 2
|
150
|
-
[bytes[0..3]._flip._to_uint >> 2, bytes[4..]]
|
151
|
-
when 3
|
152
|
-
length = 4 + (bytes[0] >> 2)
|
153
|
-
[bytes[1..length]._flip._to_uint, bytes[length + 1..]]
|
154
|
-
else
|
155
|
-
raise Unreachable, 'type: Compact'
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def _encode_each(types, values, &encode)
|
160
|
-
_encode_each_without_merge(types, values, &encode).flatten
|
161
|
-
end
|
162
|
-
|
163
|
-
def _encode_each_without_merge(types, values, &encode)
|
164
|
-
raise LengthNotEqualErr, "types: #{types}, values: #{values.inspect}" if types.length != values.length
|
165
|
-
|
166
|
-
types.map.with_index do |type, i|
|
167
|
-
encode.call(type, values[i])
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def _encode_types(types, values, registry = {})
|
172
|
-
_encode_each(types, values) do |type, value|
|
173
|
-
encode(type, value, registry)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def _encode_each_with_hashers(types, values, hashers, &encode)
|
178
|
-
if !hashers.nil? && hashers.length != types.length
|
179
|
-
raise ScaleRb::LengthNotEqualErr, "types length: #{types.length}, hashers length: #{hashers.length}"
|
180
|
-
end
|
181
|
-
|
182
|
-
bytes_array = ScaleRb._encode_each_without_merge(types, values, &encode)
|
183
|
-
bytes_array.each_with_index.reduce([]) do |memo, (bytes, i)|
|
184
|
-
memo + Hasher.apply_hasher(hashers[i], bytes)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
module ScaleRb
|
191
|
-
# Decode
|
192
|
-
class << self
|
193
|
-
def decode(type, bytes, registry = {})
|
194
|
-
# logger.debug '--------------------------------------------------'
|
195
|
-
# debug 'decoding type', type
|
196
|
-
# debug 'bytes', bytes&.length
|
197
|
-
|
198
|
-
if type.instance_of?(String)
|
199
|
-
return decode_bytes(bytes) if bytes?(type) # Bytes
|
200
|
-
return decode_boolean(bytes) if boolean?(type) # Boolean
|
201
|
-
return decode_string(bytes) if string?(type) # String
|
202
|
-
return decode_int(type, bytes) if int?(type) # i8, i16...
|
203
|
-
return decode_uint(type, bytes) if uint?(type) # u8, u16...
|
204
|
-
return decode_compact(bytes) if compact?(type) # Compact<>
|
205
|
-
return decode_option(type, bytes, registry) if option?(type) # Option<>
|
206
|
-
return decode_array(type, bytes, registry) if array?(type) # [u8; 3]
|
207
|
-
return decode_vec(type, bytes, registry) if vec?(type) # Vec<u8>
|
208
|
-
return decode_tuple(type, bytes, registry) if tuple?(type) # (u8, u8)
|
209
|
-
|
210
|
-
# search the type from registry if not the types above
|
211
|
-
registry_type = _get_final_type_from_registry(registry, type)
|
212
|
-
return decode(registry_type, bytes, registry) if registry_type
|
213
|
-
elsif type.instance_of?(Hash)
|
214
|
-
return decode_enum(type, bytes, registry) if enum?(type)
|
215
|
-
return decode_struct(type, bytes, registry) if struct?(type)
|
216
|
-
end
|
217
|
-
|
218
|
-
raise NotImplemented, "type: #{type.inspect}"
|
219
|
-
end
|
220
|
-
|
221
|
-
def decode_bytes(bytes)
|
222
|
-
length, remaining_bytes = _do_decode_compact(bytes)
|
223
|
-
value = remaining_bytes[0...length]._to_hex
|
224
|
-
# debug 'length', length
|
225
|
-
# debug 'value', value
|
226
|
-
[
|
227
|
-
value,
|
228
|
-
remaining_bytes[length..]
|
229
|
-
]
|
230
|
-
end
|
231
|
-
|
232
|
-
def decode_boolean(bytes)
|
233
|
-
value =
|
234
|
-
if bytes[0] == 0x00
|
235
|
-
false
|
236
|
-
elsif bytes[0] == 0x01
|
237
|
-
true
|
238
|
-
else
|
239
|
-
raise InvalidBytesError, 'type: Boolean'
|
240
|
-
end
|
241
|
-
# debug 'value', value
|
242
|
-
[value, bytes[1..]]
|
243
|
-
end
|
244
|
-
|
245
|
-
def decode_string(bytes)
|
246
|
-
length, remaining_bytes = _do_decode_compact(bytes)
|
247
|
-
raise NotEnoughBytesError, 'type: String' if remaining_bytes.length < length
|
248
|
-
|
249
|
-
value = remaining_bytes[0...length]._to_utf8
|
250
|
-
# debug 'byte length', length
|
251
|
-
# debug 'value', value.inspect
|
252
|
-
[
|
253
|
-
value,
|
254
|
-
remaining_bytes[length..]
|
255
|
-
]
|
256
|
-
end
|
257
|
-
|
258
|
-
def decode_int(type, bytes)
|
259
|
-
bit_length = type[1..].to_i
|
260
|
-
byte_length = bit_length / 8
|
261
|
-
raise NotEnoughBytesError, "type: #{type}" if bytes.length < byte_length
|
262
|
-
|
263
|
-
value = bytes[0...byte_length]._flip._to_int(bit_length)
|
264
|
-
# debug 'value', value
|
265
|
-
[
|
266
|
-
value,
|
267
|
-
bytes[byte_length..]
|
268
|
-
]
|
269
|
-
end
|
270
|
-
|
271
|
-
def decode_uint(type_def, bytes)
|
272
|
-
bit_length = type_def[1..].to_i
|
273
|
-
byte_length = bit_length / 8
|
274
|
-
raise NotEnoughBytesError, "type: #{type_def}" if bytes.length < byte_length
|
275
|
-
|
276
|
-
value = bytes[0...byte_length]._flip._to_uint
|
277
|
-
# debug 'value', value
|
278
|
-
[
|
279
|
-
value,
|
280
|
-
bytes[byte_length..]
|
281
|
-
]
|
282
|
-
end
|
283
|
-
|
284
|
-
def decode_compact(bytes)
|
285
|
-
_do_decode_compact(bytes)
|
286
|
-
# debug 'value', result[0]
|
287
|
-
end
|
288
|
-
|
289
|
-
def decode_option(type_def, bytes, registry = {})
|
290
|
-
inner_type = parse_option(type_def)
|
291
|
-
|
292
|
-
return [nil, bytes[1..]] if bytes[0] == 0x00
|
293
|
-
return decode(inner_type, bytes[1..], registry) if bytes[0] == 0x01
|
294
|
-
|
295
|
-
raise InvalidBytesError, "type: #{type_def}"
|
296
|
-
end
|
297
|
-
|
298
|
-
def decode_array(type_def, bytes, registry = {})
|
299
|
-
inner_type, length = parse_array(type_def)
|
300
|
-
_decode_types([inner_type] * length, bytes, registry)
|
301
|
-
end
|
302
|
-
|
303
|
-
def decode_vec(type_def, bytes, registry = {})
|
304
|
-
inner_type = parse_vec(type_def)
|
305
|
-
length, remaining_bytes = _do_decode_compact(bytes)
|
306
|
-
# debug 'length', length
|
307
|
-
_decode_types([inner_type] * length, remaining_bytes, registry)
|
308
|
-
end
|
309
|
-
|
310
|
-
def decode_tuple(type_def, bytes, registry = {})
|
311
|
-
inner_types = parse_tuple(type_def)
|
312
|
-
_decode_types(inner_types, bytes, registry)
|
313
|
-
end
|
314
|
-
|
315
|
-
# TODO: custom index?
|
316
|
-
# {
|
317
|
-
# _enum: {
|
318
|
-
# name1: type1,
|
319
|
-
# name2: type2
|
320
|
-
# }
|
321
|
-
# }
|
322
|
-
# or
|
323
|
-
# {
|
324
|
-
# _enum: ['name1', 'name2']
|
325
|
-
# }
|
326
|
-
def decode_enum(type_def, bytes, registry = {})
|
327
|
-
index = bytes[0]
|
328
|
-
|
329
|
-
items = type_def[:_enum]
|
330
|
-
raise IndexOutOfRangeError, "type: #{type_def}" if index > items.length - 1
|
331
|
-
|
332
|
-
item = items.to_a[index] # 'name' or [:name, inner_type]
|
333
|
-
# debug 'value', item.inspect
|
334
|
-
return [item, bytes[1..]] if item.instance_of?(String)
|
335
|
-
|
336
|
-
value, remaining_bytes = decode(item[1], bytes[1..], registry)
|
337
|
-
[
|
338
|
-
{ item[0].to_sym => value },
|
339
|
-
remaining_bytes
|
340
|
-
]
|
341
|
-
end
|
342
|
-
|
343
|
-
def decode_struct(struct, bytes, registry = {})
|
344
|
-
values, remaining_bytes = _decode_types(struct.values, bytes, registry)
|
345
|
-
[
|
346
|
-
[struct.keys, values].transpose.to_h,
|
347
|
-
remaining_bytes
|
348
|
-
]
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
# Encode
|
353
|
-
class << self
|
354
|
-
def encode(type, value, registry = {})
|
355
|
-
# logger.debug '--------------------------------------------------'
|
356
|
-
# debug 'encoding type', type
|
357
|
-
# debug 'value', value
|
358
|
-
|
359
|
-
if type.instance_of?(String)
|
360
|
-
return encode_bytes(value) if bytes?(type)
|
361
|
-
return encode_boolean(value) if boolean?(type)
|
362
|
-
return encode_string(value) if string?(type)
|
363
|
-
return encode_compact(value) if compact?(type)
|
364
|
-
return encode_uint(type, value) if uint?(type)
|
365
|
-
return encode_option(type, value, registry) if option?(type)
|
366
|
-
return encode_array(type, value, registry) if array?(type)
|
367
|
-
return encode_vec(type, value, registry) if vec?(type)
|
368
|
-
return encode_tuple(type, value, registry) if tuple?(type)
|
369
|
-
|
370
|
-
registry_type = _get_final_type_from_registry(registry, type)
|
371
|
-
return encode(registry_type, value, registry) if registry_type
|
372
|
-
elsif type.instance_of?(Hash)
|
373
|
-
return encode_enum(type, value, registry) if enum?(type)
|
374
|
-
return encode_struct(type, value, registry) if struct?(type)
|
375
|
-
end
|
376
|
-
|
377
|
-
raise NotImplemented, "type: #{type}, value: #{value.inspect}"
|
378
|
-
end
|
379
|
-
|
380
|
-
def encode_bytes(value)
|
381
|
-
encode_compact(value.length) + value
|
382
|
-
end
|
383
|
-
|
384
|
-
def encode_boolean(value)
|
385
|
-
return [0x00] if value == false
|
386
|
-
return [0x01] if value == true
|
387
|
-
|
388
|
-
raise InvalidValueError, "type: Boolean, value: #{value.inspect}"
|
389
|
-
end
|
390
|
-
|
391
|
-
def encode_string(string)
|
392
|
-
body = string.unpack('C*')
|
393
|
-
prefix = encode_compact(body.length)
|
394
|
-
prefix + body
|
395
|
-
end
|
396
|
-
|
397
|
-
def encode_compact(value)
|
398
|
-
return [value << 2] if (value >= 0) && (value < 64)
|
399
|
-
return ((value << 2) + 1)._to_bytes._flip if value < 2**14
|
400
|
-
return ((value << 2) + 2)._to_bytes._flip if value < 2**30
|
401
|
-
|
402
|
-
bytes = value._to_bytes._flip
|
403
|
-
[(((bytes.length - 4) << 2) + 3)] + bytes
|
404
|
-
end
|
405
|
-
|
406
|
-
def encode_uint(type, value)
|
407
|
-
raise InvalidValueError, "type: #{type}, value: #{value.inspect}" unless value.instance_of?(Integer)
|
408
|
-
|
409
|
-
bit_length = type[1..].to_i
|
410
|
-
value._to_bytes(bit_length)._flip
|
411
|
-
end
|
412
|
-
|
413
|
-
def encode_option(type, value, registry = {})
|
414
|
-
return [0x00] if value.nil?
|
415
|
-
|
416
|
-
inner_type = type.scan(/\A[O|o]ption<(.+)>\z/).first.first
|
417
|
-
[0x01] + encode(inner_type, value, registry)
|
418
|
-
end
|
419
|
-
|
420
|
-
def encode_array(type, array, registry = {})
|
421
|
-
inner_type, length = parse_array(type)
|
422
|
-
raise LengthNotEqualErr, "type: #{type}, value: #{array.inspect}" if length != array.length
|
423
|
-
|
424
|
-
_encode_types([inner_type] * length, array, registry)
|
425
|
-
end
|
426
|
-
|
427
|
-
def encode_vec(type, array, registry = {})
|
428
|
-
inner_type = type.scan(/\A[V|v]ec<(.+)>\z/).first.first
|
429
|
-
length_bytes = encode_compact(array.length)
|
430
|
-
length_bytes + _encode_types([inner_type] * array.length, array, registry)
|
431
|
-
end
|
432
|
-
|
433
|
-
def encode_tuple(tuple_type, tuple, registry = {})
|
434
|
-
inner_types = tuple_type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
|
435
|
-
_encode_types(inner_types, tuple, registry)
|
436
|
-
end
|
437
|
-
|
438
|
-
def encode_enum(enum_type, enum, registry = {})
|
439
|
-
key = enum.keys.first
|
440
|
-
value = enum.values.first
|
441
|
-
value_type = enum_type[:_enum][key]
|
442
|
-
index = enum_type[:_enum].keys.index(key)
|
443
|
-
encode_uint('u8', index) + encode(value_type, value, registry)
|
444
|
-
end
|
445
|
-
|
446
|
-
def encode_struct(struct_type, struct, registry = {})
|
447
|
-
_encode_types(struct_type.values, struct.values, registry)
|
448
|
-
end
|
449
|
-
end
|
450
|
-
end
|
data/lib/metadata/metadata.rb
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ScaleRb
|
4
|
-
module Metadata
|
5
|
-
class << self
|
6
|
-
def decode_metadata(bytes)
|
7
|
-
metadata, = ScaleRb.decode('MetadataTop', bytes, TYPES)
|
8
|
-
metadata
|
9
|
-
end
|
10
|
-
|
11
|
-
def build_registry(metadata)
|
12
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless metadata._get(:metadata)._key?(:v14)
|
13
|
-
|
14
|
-
metadata_v14 = metadata._get(:metadata)._get(:v14)
|
15
|
-
MetadataV14.build_registry(metadata_v14)
|
16
|
-
end
|
17
|
-
|
18
|
-
def get_module(pallet_name, metadata)
|
19
|
-
version = metadata._get(:metadata).keys.first
|
20
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
21
|
-
v14].include?(version.to_s)
|
22
|
-
|
23
|
-
Metadata.const_get("Metadata#{version.upcase}").get_module(pallet_name, metadata)
|
24
|
-
end
|
25
|
-
|
26
|
-
def get_module_by_index(pallet_index, metadata)
|
27
|
-
version = metadata._get(:metadata).keys.first
|
28
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
29
|
-
v14].include?(version.to_s)
|
30
|
-
|
31
|
-
Metadata.const_get("Metadata#{version.upcase}").get_module_by_index(pallet_index, metadata)
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_storage_item(pallet_name, item_name, metadata)
|
35
|
-
version = metadata._get(:metadata).keys.first
|
36
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
37
|
-
v14].include?(version.to_s)
|
38
|
-
|
39
|
-
Metadata.const_get("Metadata#{version.upcase}").get_storage_item(pallet_name, item_name, metadata)
|
40
|
-
end
|
41
|
-
|
42
|
-
def get_calls_type(pallet_name, metadata)
|
43
|
-
version = metadata._get(:metadata).keys.first
|
44
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
45
|
-
v14].include?(version.to_s)
|
46
|
-
|
47
|
-
Metadata.const_get("Metadata#{version.upcase}").get_calls_type(pallet_name, metadata)
|
48
|
-
end
|
49
|
-
|
50
|
-
def get_calls_type_id(pallet_name, metadata)
|
51
|
-
version = metadata._get(:metadata).keys.first
|
52
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
53
|
-
v14].include?(version.to_s)
|
54
|
-
|
55
|
-
Metadata.const_get("Metadata#{version.upcase}").get_calls_type_id(pallet_name, metadata)
|
56
|
-
end
|
57
|
-
|
58
|
-
def get_call_type(pallet_name, call_name, metadata)
|
59
|
-
version = metadata._get(:metadata).keys.first
|
60
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
61
|
-
v14].include?(version.to_s)
|
62
|
-
|
63
|
-
Metadata.const_get("Metadata#{version.upcase}").get_call_type(pallet_name, call_name, metadata)
|
64
|
-
end
|
65
|
-
|
66
|
-
# call examples:
|
67
|
-
# {:pallet_name=>"Deposit", :call_name=>"Claim", :call=>["claim", []]}
|
68
|
-
# {:pallet_name=>"Balances", :call_name=>"Transfer", :call=>[{:transfer=>{:dest=>[10, 18, 135, 151, 117, 120, 248, 136, 189, 193, 199, 98, 119, 129, 175, 28, 192, 0, 230, 171], :value=>11000000000000000000}}, []]}
|
69
|
-
def encode_call(call, metadata)
|
70
|
-
calls_type_id = get_calls_type_id(call[:pallet_name], metadata)
|
71
|
-
pallet_index = get_module(call[:pallet_name], metadata)._get(:index)
|
72
|
-
[pallet_index] + PortableCodec.encode(calls_type_id, call[:call].first, build_registry(metadata))
|
73
|
-
end
|
74
|
-
|
75
|
-
# callbytes's structure is: pallet_index + call_index + argsbytes
|
76
|
-
#
|
77
|
-
# callbytes examples:
|
78
|
-
# "0x0901"._to_bytes
|
79
|
-
# "0x05000a1287977578f888bdc1c7627781af1cc000e6ab1300004c31b8d9a798"._to_bytes
|
80
|
-
def decode_call(callbytes, metadata)
|
81
|
-
pallet_index = callbytes[0]
|
82
|
-
pallet = get_module_by_index(pallet_index, metadata)
|
83
|
-
|
84
|
-
pallet_name = pallet._get(:name)
|
85
|
-
|
86
|
-
# Remove the pallet_index
|
87
|
-
# The callbytes we used below should not contain the pallet index.
|
88
|
-
# This is because the pallet index is not part of the call type.
|
89
|
-
# Its structure is: call_index + call_args
|
90
|
-
callbytes_without_pallet_index = callbytes[1..]
|
91
|
-
calls_type_id = pallet._get(:calls)._get(:type)
|
92
|
-
decoded = PortableCodec.decode(
|
93
|
-
calls_type_id,
|
94
|
-
callbytes_without_pallet_index,
|
95
|
-
build_registry(metadata)
|
96
|
-
)
|
97
|
-
|
98
|
-
{
|
99
|
-
pallet_name: pallet_name,
|
100
|
-
call_name: decoded.first.is_a?(String) ? decoded.first._to_camel : decoded.first.keys.first.to_s._to_camel,
|
101
|
-
call: decoded
|
102
|
-
}
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
TYPES = {
|
107
|
-
'MetadataTop' => {
|
108
|
-
magicNumber: 'U32',
|
109
|
-
metadata: 'Metadata'
|
110
|
-
},
|
111
|
-
'Metadata' => {
|
112
|
-
_enum: {
|
113
|
-
v0: 'MetadataV0',
|
114
|
-
v1: 'MetadataV1',
|
115
|
-
v2: 'MetadataV2',
|
116
|
-
v3: 'MetadataV3',
|
117
|
-
v4: 'MetadataV4',
|
118
|
-
v5: 'MetadataV5',
|
119
|
-
v6: 'MetadataV6',
|
120
|
-
v7: 'MetadataV7',
|
121
|
-
v8: 'MetadataV8',
|
122
|
-
v9: 'MetadataV9',
|
123
|
-
v10: 'MetadataV10',
|
124
|
-
v11: 'MetadataV11',
|
125
|
-
v12: 'MetadataV12',
|
126
|
-
v13: 'MetadataV13',
|
127
|
-
v14: 'MetadataV14'
|
128
|
-
}
|
129
|
-
}
|
130
|
-
}.merge(MetadataV14::TYPES)
|
131
|
-
.merge(MetadataV13::TYPES)
|
132
|
-
.merge(MetadataV12::TYPES)
|
133
|
-
.merge(MetadataV11::TYPES)
|
134
|
-
.merge(MetadataV10::TYPES)
|
135
|
-
.merge(MetadataV9::TYPES)
|
136
|
-
end
|
137
|
-
end
|
data/lib/monkey_patching.rb
DELETED
@@ -1,115 +0,0 @@
|
|
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
|
-
elsif key.instance_of?(Symbol)
|
110
|
-
self[key] || self[key.to_s]
|
111
|
-
else
|
112
|
-
self[key]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|