scale_rb 0.5.0 → 0.5.2
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/bin/console +0 -0
- data/examples/http_client_3.rb +84 -0
- data/exe/metadata +1 -1
- data/lib/scale_rb/call_helper.rb +5 -5
- data/lib/scale_rb/client/{client_ext.rb → client_share.rb} +12 -6
- data/lib/scale_rb/client/http_client.rb +2 -2
- data/lib/scale_rb/client/ws_client.rb +2 -2
- data/lib/scale_rb/decode.rb +17 -0
- data/lib/scale_rb/extrinsic_helper.rb +50 -0
- data/lib/scale_rb/metadata/metadata.rb +213 -65
- data/lib/scale_rb/metadata/metadata_v10.rb +40 -40
- data/lib/scale_rb/metadata/metadata_v11.rb +44 -44
- data/lib/scale_rb/metadata/metadata_v12.rb +22 -22
- data/lib/scale_rb/metadata/metadata_v13.rb +45 -45
- data/lib/scale_rb/metadata/metadata_v14.rb +123 -117
- data/lib/scale_rb/metadata/metadata_v9.rb +56 -56
- data/lib/scale_rb/old_registry.rb +552 -0
- data/lib/scale_rb/portable_registry.rb +30 -12
- data/lib/scale_rb/storage_helper.rb +9 -5
- data/lib/scale_rb/types.rb +9 -2
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +3 -1
- metadata +7 -6
- data/lib/scale_rb/metadata/registry.rb +0 -263
- data/lib/scale_rb/metadata/type_exp.rb +0 -286
@@ -0,0 +1,552 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './types'
|
4
|
+
|
5
|
+
# rubocop:disable all
|
6
|
+
module ScaleRb
|
7
|
+
class OldRegistry
|
8
|
+
include Types
|
9
|
+
|
10
|
+
# Map name to index of type in `types` array
|
11
|
+
# % lookup :: String -> Integer
|
12
|
+
attr_reader :lookup
|
13
|
+
|
14
|
+
# % keys :: Integer -> String
|
15
|
+
attr_reader :keys
|
16
|
+
|
17
|
+
# % types :: Array<PortableType>
|
18
|
+
attr_reader :types
|
19
|
+
|
20
|
+
attr_reader :old_types
|
21
|
+
|
22
|
+
# % initialize :: Hash<String, Any> -> void
|
23
|
+
def initialize(old_types)
|
24
|
+
@old_types = old_types
|
25
|
+
@lookup = {}
|
26
|
+
@keys = {}
|
27
|
+
@types = []
|
28
|
+
|
29
|
+
build()
|
30
|
+
end
|
31
|
+
|
32
|
+
def build()
|
33
|
+
@old_types.keys.each do |name|
|
34
|
+
use(name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](identifier)
|
39
|
+
if identifier.is_a?(::Integer)
|
40
|
+
@types[identifier]
|
41
|
+
elsif identifier.is_a?(::String)
|
42
|
+
@types[use(identifier)]
|
43
|
+
else
|
44
|
+
raise "Unknown identifier type: #{identifier.class}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def inspect
|
49
|
+
"registry(#{@types.length} types)"
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s
|
53
|
+
@types.map.with_index do |type, index|
|
54
|
+
"#{@keys[index]} => #{type.to_s}"
|
55
|
+
end.join("\n")
|
56
|
+
end
|
57
|
+
|
58
|
+
# % use :: String -> Integer
|
59
|
+
def use(old_type_exp)
|
60
|
+
raise "Empty old_type_exp: #{old_type_exp}" if old_type_exp.nil? || old_type_exp.strip == ''
|
61
|
+
|
62
|
+
ast_type = TypeExp.parse(old_type_exp)
|
63
|
+
raise "No AST type for #{old_type_exp}" if ast_type.nil?
|
64
|
+
|
65
|
+
key = ast_type.to_s
|
66
|
+
ti = lookup[key]
|
67
|
+
return ti if ti
|
68
|
+
|
69
|
+
ti = @types.length
|
70
|
+
@types[ti] = "Placeholder"
|
71
|
+
@lookup[key] = ti
|
72
|
+
@keys[ti] = key
|
73
|
+
@types[ti] = build_portable_type(ast_type)
|
74
|
+
ti
|
75
|
+
end
|
76
|
+
|
77
|
+
# % build_portable_type :: NamedType | ArrayType | TupleType -> PortableType
|
78
|
+
# __ :build_portable_type, { ast_type: TypedArray[TypeExp::ArrayType | TypeExp::TupleType | TypeExp::NamedType] } => PortableType
|
79
|
+
def build_portable_type(ast_type)
|
80
|
+
case ast_type
|
81
|
+
when TypeExp::ArrayType
|
82
|
+
ArrayType.new(use(ast_type.item), ast_type.len, registry: self)
|
83
|
+
when TypeExp::TupleType
|
84
|
+
TupleType.new(ast_type.params.map { |param| use(param) })
|
85
|
+
when TypeExp::NamedType
|
86
|
+
build_portable_type_from_named_type(ast_type)
|
87
|
+
else
|
88
|
+
raise "Unknown type: #{ast_type.class}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# % build_portable_type_from_named_type :: NamedType -> PortableType
|
93
|
+
def build_portable_type_from_named_type(named_type)
|
94
|
+
name = named_type.name
|
95
|
+
params = named_type.params
|
96
|
+
|
97
|
+
definition = @old_types[name]
|
98
|
+
return build_from_definition(name, definition) if definition
|
99
|
+
|
100
|
+
primitive = as_primitive(name)
|
101
|
+
return primitive if primitive
|
102
|
+
|
103
|
+
case name
|
104
|
+
when 'Vec'
|
105
|
+
item_index = use(params[0].to_s)
|
106
|
+
SequenceType.new(type: item_index, registry: self)
|
107
|
+
when 'Option'
|
108
|
+
item_index = use(params[0].to_s)
|
109
|
+
VariantType.option(item_index, self)
|
110
|
+
when 'Result'
|
111
|
+
ok_index = use(params[0].to_s)
|
112
|
+
err_index = use(params[1].to_s)
|
113
|
+
VariantType.result(ok_index, err_index, self)
|
114
|
+
when 'Compact'
|
115
|
+
# item_index = use(params[0].to_s)
|
116
|
+
# CompactType.new(type: item_index, registry: self)
|
117
|
+
CompactType.new
|
118
|
+
when 'Null'
|
119
|
+
UnitType.new
|
120
|
+
else
|
121
|
+
raise "Unknown type: #{name}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# % as_primitive :: String -> PrimitiveType | nil
|
126
|
+
def as_primitive(name)
|
127
|
+
case name.downcase
|
128
|
+
when /^i\d+$/
|
129
|
+
PrimitiveType.new(primitive: "I#{name[1..]}".to_sym)
|
130
|
+
when /^u\d+$/
|
131
|
+
PrimitiveType.new(primitive: "U#{name[1..]}".to_sym)
|
132
|
+
when /^bool$/
|
133
|
+
PrimitiveType.new(primitive: :Bool)
|
134
|
+
when /^str$/, /^text$/
|
135
|
+
PrimitiveType.new(primitive: :Str)
|
136
|
+
else
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# % build_from_definition :: String -> OldTypeDefinition -> PortableType | TypeAlias
|
142
|
+
#
|
143
|
+
# type OldTypeDefinition = String | OldEnumDefinition | OldStructDefinition
|
144
|
+
# type OldEnumDefinition = {
|
145
|
+
# _enum: String[] | Hash<Symbol, Any>,
|
146
|
+
# }
|
147
|
+
# type OldStructDefinition = {
|
148
|
+
# _struct: Hash<Symbol, Any>
|
149
|
+
# }
|
150
|
+
def build_from_definition(name, definition) # rubocop:disable Metrics/MethodLength
|
151
|
+
case definition
|
152
|
+
when String
|
153
|
+
# TypeAlias.new(name, use(definition))
|
154
|
+
alias_type_id = use(definition)
|
155
|
+
# p "alias_type_id: #{alias_type_id}"
|
156
|
+
types[alias_type_id]
|
157
|
+
when Hash
|
158
|
+
if definition['_enum']
|
159
|
+
_build_portable_type_from_enum_definition(definition)
|
160
|
+
elsif definition['_set']
|
161
|
+
raise 'Sets are not supported'
|
162
|
+
else
|
163
|
+
_build_portable_type_from_struct_definition(definition)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
def _indexed_enum?(definition)
|
171
|
+
definition['_enum'].is_a?(::Hash) && definition['_enum'].values.all? { |value| value.is_a?(::Integer) }
|
172
|
+
end
|
173
|
+
|
174
|
+
# % _build_portable_type_from_enum_definition :: Hash<Symbol, Any> -> VariantType
|
175
|
+
# { '_enum' => ['A', 'B', 'C'] }
|
176
|
+
def _build_portable_type_from_enum_definition(definition)
|
177
|
+
variants =
|
178
|
+
if definition['_enum'].is_a?(::Array)
|
179
|
+
# Simple array enum:
|
180
|
+
# {
|
181
|
+
# '_enum' => ['A', 'B', 'C']
|
182
|
+
# }
|
183
|
+
definition['_enum'].map.with_index do |variant_name, index|
|
184
|
+
SimpleVariant.new(name: variant_name.to_sym, index:)
|
185
|
+
end
|
186
|
+
elsif definition['_enum'].is_a?(::Hash)
|
187
|
+
if _indexed_enum?(definition)
|
188
|
+
# Indexed enum:
|
189
|
+
# {
|
190
|
+
# '_enum' => {
|
191
|
+
# 'Variant1' => 0,
|
192
|
+
# 'Variant2' => 1,
|
193
|
+
# 'Variant3' => 2
|
194
|
+
# }
|
195
|
+
# }
|
196
|
+
definition['_enum'].map do |variant_name, index|
|
197
|
+
SimpleVariant.new(name: variant_name.to_sym, index:)
|
198
|
+
end
|
199
|
+
else
|
200
|
+
# Mixed enum:
|
201
|
+
# {
|
202
|
+
# '_enum' => {
|
203
|
+
# 'A' => 'u32',
|
204
|
+
# 'B' => {a: 'u32', b: 'u32'},
|
205
|
+
# 'C' => null,
|
206
|
+
# 'D' => ['u32', 'u32']
|
207
|
+
# }
|
208
|
+
# }
|
209
|
+
definition['_enum'].map.with_index do |(variant_name, variant_def), index|
|
210
|
+
case variant_def
|
211
|
+
when ::String
|
212
|
+
TupleVariant.new(
|
213
|
+
name: variant_name.to_sym,
|
214
|
+
index:,
|
215
|
+
tuple: TupleType.new(
|
216
|
+
tuple: [use(variant_def)],
|
217
|
+
registry: self
|
218
|
+
),
|
219
|
+
)
|
220
|
+
when ::Array
|
221
|
+
TupleVariant.new(
|
222
|
+
name: variant_name.to_sym,
|
223
|
+
index:,
|
224
|
+
tuple: TupleType.new(
|
225
|
+
tuple: variant_def.map { |field_type| use(field_type) },
|
226
|
+
registry: self
|
227
|
+
)
|
228
|
+
)
|
229
|
+
when ::Hash
|
230
|
+
StructVariant.new(
|
231
|
+
name: variant_name.to_sym,
|
232
|
+
index:,
|
233
|
+
struct: StructType.new(
|
234
|
+
fields: variant_def.map do |field_name, field_type|
|
235
|
+
Field.new(name: field_name.to_s, type: use(field_type))
|
236
|
+
end,
|
237
|
+
registry: self
|
238
|
+
)
|
239
|
+
)
|
240
|
+
else
|
241
|
+
raise "Unknown variant type for #{variant_name}: #{variant_def.class}"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
VariantType.new(variants:, registry: self)
|
247
|
+
end
|
248
|
+
|
249
|
+
# % _build_portable_type_from_struct_definition :: Hash<String, Any> -> StructType
|
250
|
+
def _build_portable_type_from_struct_definition(definition)
|
251
|
+
fields = definition.map do |field_name, field_type|
|
252
|
+
Field.new(name: field_name.to_s, type: use(field_type))
|
253
|
+
end
|
254
|
+
StructType.new(fields:, registry: self)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
module ScaleRb
|
260
|
+
class OldRegistry
|
261
|
+
module TypeExp
|
262
|
+
class Tokenizer
|
263
|
+
attr_reader :tokens, :index
|
264
|
+
|
265
|
+
# % tokenize :: String -> [String]
|
266
|
+
def initialize(type_exp)
|
267
|
+
@tokens = tokenize(type_exp)
|
268
|
+
@index = 0
|
269
|
+
end
|
270
|
+
|
271
|
+
# % next_token :: -> String
|
272
|
+
def next_token
|
273
|
+
token = @tokens[@index]
|
274
|
+
@index += 1
|
275
|
+
token
|
276
|
+
end
|
277
|
+
|
278
|
+
# % peek_token :: -> String
|
279
|
+
def peek_token
|
280
|
+
@tokens[@index]
|
281
|
+
end
|
282
|
+
|
283
|
+
# % eof? :: -> Bool
|
284
|
+
def eof?
|
285
|
+
@index >= @tokens.length
|
286
|
+
end
|
287
|
+
|
288
|
+
private
|
289
|
+
|
290
|
+
def tokenize(type_exp)
|
291
|
+
tokens = []
|
292
|
+
current_token = ''
|
293
|
+
|
294
|
+
type_exp.each_char do |char|
|
295
|
+
case char
|
296
|
+
when /[a-zA-Z0-9_]/
|
297
|
+
current_token += char
|
298
|
+
when ':', '<', '>', '(', ')', '[', ']', ',', ';', '&', "'"
|
299
|
+
tokens << current_token unless current_token.empty?
|
300
|
+
if char == ':' && tokens.last == ':'
|
301
|
+
tokens[-1] = '::'
|
302
|
+
else
|
303
|
+
tokens << char
|
304
|
+
end
|
305
|
+
current_token = ''
|
306
|
+
when /\s/
|
307
|
+
tokens << current_token unless current_token.empty?
|
308
|
+
current_token = ''
|
309
|
+
else
|
310
|
+
raise abort
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
tokens << current_token unless current_token.empty?
|
315
|
+
tokens
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
class NamedType
|
320
|
+
attr_reader :name, :params
|
321
|
+
|
322
|
+
def initialize(name, params)
|
323
|
+
@name = name
|
324
|
+
@params = params
|
325
|
+
end
|
326
|
+
|
327
|
+
def to_s
|
328
|
+
params.empty? ? name : "#{name}<#{params.map(&:to_s).join(', ')}>"
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
class ArrayType
|
333
|
+
attr_reader :item, :len
|
334
|
+
|
335
|
+
def initialize(item, len)
|
336
|
+
@item = item
|
337
|
+
@len = len
|
338
|
+
end
|
339
|
+
|
340
|
+
def to_s
|
341
|
+
"[#{item}; #{len}]"
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
class TupleType
|
346
|
+
attr_reader :params
|
347
|
+
|
348
|
+
def initialize(params)
|
349
|
+
@params = params
|
350
|
+
end
|
351
|
+
|
352
|
+
def to_s
|
353
|
+
"(#{params.map(&:to_s).join(', ')})"
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# % print :: NamedType | ArrayType | TupleType -> String
|
358
|
+
def self.print(type)
|
359
|
+
type.to_s
|
360
|
+
end
|
361
|
+
|
362
|
+
# % parse :: String -> NamedType | ArrayType | TupleType
|
363
|
+
def self.parse(type_exp)
|
364
|
+
TypeExpParser.new(type_exp).parse
|
365
|
+
end
|
366
|
+
|
367
|
+
class TypeExpParser
|
368
|
+
def initialize(type_exp)
|
369
|
+
@type_exp = type_exp
|
370
|
+
@tokenizer = Tokenizer.new(type_exp)
|
371
|
+
@current_token = @tokenizer.next_token
|
372
|
+
end
|
373
|
+
|
374
|
+
def parse
|
375
|
+
build_type
|
376
|
+
end
|
377
|
+
|
378
|
+
private
|
379
|
+
|
380
|
+
# Consume and return the current token, or nil if it doesn't equal the expected token.
|
381
|
+
def expect(token)
|
382
|
+
return unless @current_token == token
|
383
|
+
|
384
|
+
current_token = @current_token
|
385
|
+
@current_token = @tokenizer.next_token
|
386
|
+
current_token
|
387
|
+
end
|
388
|
+
|
389
|
+
def expect!(token)
|
390
|
+
expect(token) || raise("Expected #{token}, got #{@current_token}")
|
391
|
+
end
|
392
|
+
|
393
|
+
# Consume and return the current token if it matches the expected regex pattern.
|
394
|
+
def expect_regex(pattern)
|
395
|
+
return unless pattern.match?(@current_token)
|
396
|
+
|
397
|
+
current_token = @current_token
|
398
|
+
@current_token = @tokenizer.next_token
|
399
|
+
current_token
|
400
|
+
end
|
401
|
+
|
402
|
+
def expect_regex!(pattern)
|
403
|
+
expect_regex(pattern) || raise("Expected current token matching #{pattern.inspect}, got #{@current_token}")
|
404
|
+
end
|
405
|
+
|
406
|
+
# Consume and return a natural number (integer) if the current token matches.
|
407
|
+
def expect_nat
|
408
|
+
expect_regex(/^\d+$/)&.to_i
|
409
|
+
end
|
410
|
+
|
411
|
+
def expect_nat!
|
412
|
+
expect_nat || raise("Expected natural number, got #{@current_token}")
|
413
|
+
end
|
414
|
+
|
415
|
+
def expect_name
|
416
|
+
expect_regex(/^[a-zA-Z]\w*$/)
|
417
|
+
end
|
418
|
+
|
419
|
+
def expect_name!
|
420
|
+
expect_name || raise("Expected name, got #{@current_token}")
|
421
|
+
end
|
422
|
+
|
423
|
+
def list(sep, &block)
|
424
|
+
result = []
|
425
|
+
item = block.call
|
426
|
+
return result if item.nil?
|
427
|
+
|
428
|
+
result << item
|
429
|
+
while expect(sep)
|
430
|
+
item = block.call
|
431
|
+
break if item.nil? # (A, B,)
|
432
|
+
|
433
|
+
result << item
|
434
|
+
end
|
435
|
+
result
|
436
|
+
end
|
437
|
+
|
438
|
+
def build_tuple_type
|
439
|
+
return nil unless expect('(')
|
440
|
+
|
441
|
+
params = list(',') { build_type }
|
442
|
+
expect!(')')
|
443
|
+
|
444
|
+
TupleType.new(params)
|
445
|
+
end
|
446
|
+
|
447
|
+
# [u8; 16; H128]
|
448
|
+
# [u8; 16]
|
449
|
+
def build_array_type
|
450
|
+
return nil unless expect('[')
|
451
|
+
|
452
|
+
item = build_type
|
453
|
+
raise "Expected array item, got #{@current_token}" if item.nil?
|
454
|
+
|
455
|
+
expect!(';')
|
456
|
+
len = expect_nat!
|
457
|
+
|
458
|
+
# [u8; 16; H128]
|
459
|
+
if expect(';')
|
460
|
+
expect_name! # Just consume the name
|
461
|
+
end
|
462
|
+
|
463
|
+
expect!(']')
|
464
|
+
ArrayType.new(item, len)
|
465
|
+
end
|
466
|
+
|
467
|
+
def build_named_type
|
468
|
+
name = nil
|
469
|
+
trait = nil
|
470
|
+
item = nil
|
471
|
+
|
472
|
+
if expect('<')
|
473
|
+
# Handle trait syntax: <T::Trait as OtherTrait>::Type
|
474
|
+
# name trait item
|
475
|
+
# '<T::InherentOfflineReport as InherentOfflineReport>::Inherent' -> 'InherentOfflineReport'
|
476
|
+
# '<T::Balance as HasCompact>' -> 'Compact<Balance>'
|
477
|
+
# '<T as Trait<I>>::Proposal' -> 'Proposal'
|
478
|
+
name = build_named_type.name
|
479
|
+
expect!('as')
|
480
|
+
trait = build_named_type.name
|
481
|
+
expect!('>')
|
482
|
+
else
|
483
|
+
name = expect_name
|
484
|
+
return if name.nil?
|
485
|
+
end
|
486
|
+
|
487
|
+
# Consume the :: and get the next name
|
488
|
+
item = expect_name while expect('::')
|
489
|
+
|
490
|
+
# Handle special cases
|
491
|
+
# From subsquid's code. But where are these coming from?
|
492
|
+
if name == 'InherentOfflineReport' && name == trait && item == 'Inherent'
|
493
|
+
# Do nothing
|
494
|
+
elsif name == 'exec' && item == 'StorageKey'
|
495
|
+
name = 'ContractStorageKey'
|
496
|
+
elsif name == 'Lookup' && item == 'Source'
|
497
|
+
name = 'LookupSource'
|
498
|
+
elsif name == 'Lookup' && item == 'Target'
|
499
|
+
name = 'LookupTarget'
|
500
|
+
elsif item
|
501
|
+
# '<T::Balance as HasCompact>::Item' will raise error
|
502
|
+
raise "Expected item, got #{item}" if trait == 'HasCompact'
|
503
|
+
|
504
|
+
name = item
|
505
|
+
elsif trait == 'HasCompact' # '<T::Balance as HasCompact>'
|
506
|
+
return NamedType.new('Compact', [NamedType.new(name, [])])
|
507
|
+
end
|
508
|
+
|
509
|
+
NamedType.new(name, type_parameters)
|
510
|
+
end
|
511
|
+
|
512
|
+
def type_parameters
|
513
|
+
if expect('<')
|
514
|
+
params = list(',') { expect_nat || build_type }
|
515
|
+
expect!('>')
|
516
|
+
else
|
517
|
+
params = []
|
518
|
+
end
|
519
|
+
|
520
|
+
params
|
521
|
+
end
|
522
|
+
|
523
|
+
# &[u8]
|
524
|
+
# &'static [u8]
|
525
|
+
def build_pointer_bytes
|
526
|
+
return nil unless expect('&') # &
|
527
|
+
|
528
|
+
expect("'") && expect!('static')
|
529
|
+
expect!('[')
|
530
|
+
expect!('u8')
|
531
|
+
expect!(']')
|
532
|
+
NamedType.new('Vec', [NamedType.new('u8', [])])
|
533
|
+
end
|
534
|
+
|
535
|
+
# % build_type :: TupleType | ArrayType | NamedType
|
536
|
+
def build_type
|
537
|
+
build_tuple_type || build_array_type || build_named_type || build_pointer_bytes
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
# require_relative '../../metadata/metadata'
|
545
|
+
|
546
|
+
# begin
|
547
|
+
# registry = ScaleRb::Metadata::Registry.new ScaleRb::Metadata::TYPES
|
548
|
+
# puts registry
|
549
|
+
# rescue StandardError => e
|
550
|
+
# puts e.message
|
551
|
+
# puts e.backtrace.join("\n")
|
552
|
+
# end
|
@@ -24,6 +24,16 @@ module ScaleRb
|
|
24
24
|
"a_portable_registry"
|
25
25
|
end
|
26
26
|
|
27
|
+
def to_s
|
28
|
+
"a_portable_registry"
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_type(type)
|
32
|
+
type_id = @types.size
|
33
|
+
@types << type
|
34
|
+
type_id
|
35
|
+
end
|
36
|
+
|
27
37
|
private
|
28
38
|
|
29
39
|
__ :build_types, {}
|
@@ -36,33 +46,39 @@ module ScaleRb
|
|
36
46
|
raise "No 'def' found: #{type}" if def_.nil?
|
37
47
|
|
38
48
|
path = type._get(:type, :path)
|
49
|
+
params = type._get(:type, :params).map do |p|
|
50
|
+
name = p._get(:name)
|
51
|
+
type = p._get(:type)
|
52
|
+
type.nil? ? Param.new(name: name) : Param.new(name: name, type: type)
|
53
|
+
end
|
39
54
|
|
40
55
|
type_name = def_.keys.first.to_sym
|
41
56
|
type_def = def_._get(type_name)
|
42
|
-
@types[id] = _build_type(id, type_name, type_def, path)
|
57
|
+
@types[id] = _build_type(id, type_name, type_def, path, params)
|
43
58
|
end
|
44
59
|
end
|
45
60
|
|
46
61
|
# TODO: type_def better type definition
|
47
|
-
__ :_build_type, { id: Ti, type_name: Symbol, type_def: Hash | String | Array, path: TypedArray[String] }, PortableType
|
48
|
-
def _build_type(id, type_name, type_def, path)
|
62
|
+
__ :_build_type, { id: Ti, type_name: Symbol, type_def: Hash | String | Array, path: TypedArray[String], params: TypedArray[Field] }, PortableType
|
63
|
+
def _build_type(id, type_name, type_def, path, params)
|
49
64
|
case type_name
|
50
65
|
when :primitive
|
51
66
|
# type_def: 'I32'
|
52
|
-
PrimitiveType.new(primitive: type_def.to_sym, path: path)
|
67
|
+
PrimitiveType.new(primitive: type_def.to_sym, path: path, params: params)
|
53
68
|
when :compact
|
54
69
|
# type_def: { type: 1 }
|
55
|
-
CompactType.new(type: type_def._get(:type), registry: self, path: path)
|
70
|
+
CompactType.new(type: type_def._get(:type), registry: self, path: path, params: params)
|
56
71
|
when :sequence
|
57
72
|
# type_def: { type: 9 }
|
58
|
-
SequenceType.new(type: type_def._get(:type), registry: self, path: path)
|
73
|
+
SequenceType.new(type: type_def._get(:type), registry: self, path: path, params: params)
|
59
74
|
when :bitSequence
|
60
75
|
# type_def: {"bitStoreType"=>2, "bitOrderType"=>502}
|
61
76
|
BitSequenceType.new(
|
62
77
|
bit_store_type: type_def._get(:bitStoreType),
|
63
78
|
bit_order_type: type_def._get(:bitOrderType),
|
64
79
|
registry: self,
|
65
|
-
path: path
|
80
|
+
path: path,
|
81
|
+
params: params
|
66
82
|
)
|
67
83
|
when :array
|
68
84
|
# type_def: { len: 3, type: 1 }
|
@@ -70,11 +86,12 @@ module ScaleRb
|
|
70
86
|
len: type_def._get(:len),
|
71
87
|
type: type_def._get(:type),
|
72
88
|
registry: self,
|
73
|
-
path: path
|
89
|
+
path: path,
|
90
|
+
params: params
|
74
91
|
)
|
75
92
|
when :tuple
|
76
93
|
# type_def: [1, 2, 3]
|
77
|
-
TupleType.new(tuple: type_def, registry: self, path: path)
|
94
|
+
TupleType.new(tuple: type_def, registry: self, path: path, params: params)
|
78
95
|
when :composite
|
79
96
|
fields = type_def._get(:fields)
|
80
97
|
first_field = fields.first
|
@@ -83,7 +100,7 @@ module ScaleRb
|
|
83
100
|
return UnitType.new(path: path) if first_field.nil?
|
84
101
|
|
85
102
|
# type_def: {"fields"=>[{"name"=>nil, "type"=>1}, {"name"=>nil, "type"=>2}]}
|
86
|
-
return TupleType.new(tuple: fields.map { |f| f._get(:type) }, registry: self, path: path) unless first_field._get(:name)
|
103
|
+
return TupleType.new(tuple: fields.map { |f| f._get(:type) }, registry: self, path: path, params: params) unless first_field._get(:name)
|
87
104
|
|
88
105
|
# type_def: { fields: [{ name: 'name', type: 1 }, { name: 'age', type: 2 }] }
|
89
106
|
StructType.new(
|
@@ -91,7 +108,8 @@ module ScaleRb
|
|
91
108
|
Field.new(name: field._get(:name), type: field._get(:type))
|
92
109
|
end,
|
93
110
|
registry: self,
|
94
|
-
path: path
|
111
|
+
path: path,
|
112
|
+
params: params
|
95
113
|
)
|
96
114
|
when :variant
|
97
115
|
variants = type_def._get(:variants)
|
@@ -126,7 +144,7 @@ module ScaleRb
|
|
126
144
|
)
|
127
145
|
end
|
128
146
|
end
|
129
|
-
VariantType.new(variants: variant_list, path: path)
|
147
|
+
VariantType.new(variants: variant_list, path: path, params: params)
|
130
148
|
end
|
131
149
|
end
|
132
150
|
end
|
@@ -53,11 +53,15 @@ module ScaleRb
|
|
53
53
|
# data: hex string
|
54
54
|
# type: portable type id
|
55
55
|
# optional: boolean
|
56
|
-
# fallback: hex string
|
56
|
+
# fallback: hex string or u8array
|
57
57
|
# returns nil or data
|
58
58
|
def decode_storage(data, type, optional, fallback, registry)
|
59
|
-
|
60
|
-
|
59
|
+
bytes = data.nil? ? nil : Utils.hex_to_u8a(data)
|
60
|
+
bytes = bytes.nil? ?
|
61
|
+
(optional ? nil : (fallback.is_a?(Array) ? fallback : Utils.hex_to_u8a(fallback))) :
|
62
|
+
bytes
|
63
|
+
|
64
|
+
ScaleRb::Codec.decode(type, bytes, registry)[0] if bytes
|
61
65
|
end
|
62
66
|
|
63
67
|
# storage_item: the storage item from metadata
|
@@ -69,8 +73,8 @@ module ScaleRb
|
|
69
73
|
end
|
70
74
|
|
71
75
|
def decode_storage3(data, pallet_name, item_name, metadata)
|
72
|
-
registry =
|
73
|
-
storage_item =
|
76
|
+
registry = metadata.build_registry
|
77
|
+
storage_item = metadata.storage(pallet_name, item_name)
|
74
78
|
decode_storage2(data, storage_item, registry)
|
75
79
|
end
|
76
80
|
end
|