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
data/lib/scale_rb/types.rb
CHANGED
@@ -10,8 +10,9 @@ module ScaleRb
|
|
10
10
|
Primitive = Types::Strict::Symbol.enum(
|
11
11
|
:I8, :U8, :I16, :U16, :I32, :U32, :I64, :U64, :I128, :U128, :I256, :U256, :Bool, :Str, :Char
|
12
12
|
)
|
13
|
-
Ti = Types::Strict::Integer
|
14
|
-
U8 = Types::Strict::Integer.constrained(gteq: 0, lt: 256)
|
13
|
+
Ti = Types::Strict::Integer | Types::Strict::String
|
14
|
+
# U8 = Types::Strict::Integer.constrained(gteq: 0, lt: 256)
|
15
|
+
U8 = Types::Strict::Integer
|
15
16
|
U8Array = Types::Strict::Array.of(U8)
|
16
17
|
Hex = Types::Strict::String.constrained(format: /\A0x[0-9a-fA-F]+\z/)
|
17
18
|
|
@@ -23,9 +24,15 @@ module ScaleRb
|
|
23
24
|
UnsignedInteger = Types::Strict::Integer.constrained(gteq: 0)
|
24
25
|
TypedArray = ->(type) { Types::Array.of(type) }
|
25
26
|
|
27
|
+
class Param < Dry::Struct
|
28
|
+
attribute :name, Types::Strict::String
|
29
|
+
attribute? :type, Ti
|
30
|
+
end
|
31
|
+
|
26
32
|
class Base < Dry::Struct
|
27
33
|
attribute? :registry, Registry
|
28
34
|
attribute? :path, Types::Strict::Array.of(Types::Strict::String)
|
35
|
+
attribute? :params, Types::Strict::Array.of(Param)
|
29
36
|
|
30
37
|
def t(type_id)
|
31
38
|
raise 'No registry' unless registry
|
data/lib/scale_rb/version.rb
CHANGED
data/lib/scale_rb.rb
CHANGED
@@ -21,16 +21,18 @@ require 'type_enforcer'
|
|
21
21
|
|
22
22
|
require 'scale_rb/types'
|
23
23
|
require 'scale_rb/portable_registry'
|
24
|
+
require 'scale_rb/old_registry'
|
24
25
|
require 'scale_rb/codec'
|
25
26
|
|
26
27
|
require 'scale_rb/metadata/metadata'
|
27
28
|
|
28
29
|
require 'scale_rb/hasher'
|
29
30
|
require 'scale_rb/storage_helper'
|
30
|
-
require 'scale_rb/
|
31
|
+
require 'scale_rb/extrinsic_helper'
|
31
32
|
|
32
33
|
require 'address'
|
33
34
|
|
34
35
|
# clients
|
36
|
+
require 'scale_rb/client/client_share'
|
35
37
|
require 'scale_rb/client/http_client'
|
36
38
|
require 'scale_rb/client/ws_client'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scale_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aki Wu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base58
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- bin/setup
|
161
161
|
- examples/http_client_1.rb
|
162
162
|
- examples/http_client_2.rb
|
163
|
+
- examples/http_client_3.rb
|
163
164
|
- examples/ws_client_1.rb
|
164
165
|
- examples/ws_client_2.rb
|
165
166
|
- examples/ws_client_3.rb
|
@@ -170,13 +171,14 @@ files:
|
|
170
171
|
- lib/custom_assign.rb
|
171
172
|
- lib/scale_rb.rb
|
172
173
|
- lib/scale_rb/call_helper.rb
|
173
|
-
- lib/scale_rb/client/
|
174
|
+
- lib/scale_rb/client/client_share.rb
|
174
175
|
- lib/scale_rb/client/http_client.rb
|
175
176
|
- lib/scale_rb/client/ws_client.rb
|
176
177
|
- lib/scale_rb/codec.rb
|
177
178
|
- lib/scale_rb/codec_utils.rb
|
178
179
|
- lib/scale_rb/decode.rb
|
179
180
|
- lib/scale_rb/encode.rb
|
181
|
+
- lib/scale_rb/extrinsic_helper.rb
|
180
182
|
- lib/scale_rb/hasher.rb
|
181
183
|
- lib/scale_rb/metadata/metadata.rb
|
182
184
|
- lib/scale_rb/metadata/metadata_v10.rb
|
@@ -185,8 +187,7 @@ files:
|
|
185
187
|
- lib/scale_rb/metadata/metadata_v13.rb
|
186
188
|
- lib/scale_rb/metadata/metadata_v14.rb
|
187
189
|
- lib/scale_rb/metadata/metadata_v9.rb
|
188
|
-
- lib/scale_rb/
|
189
|
-
- lib/scale_rb/metadata/type_exp.rb
|
190
|
+
- lib/scale_rb/old_registry.rb
|
190
191
|
- lib/scale_rb/portable_registry.rb
|
191
192
|
- lib/scale_rb/storage_helper.rb
|
192
193
|
- lib/scale_rb/types.rb
|
@@ -216,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
217
|
- !ruby/object:Gem::Version
|
217
218
|
version: '0'
|
218
219
|
requirements: []
|
219
|
-
rubygems_version: 3.5.
|
220
|
+
rubygems_version: 3.5.21
|
220
221
|
signing_key:
|
221
222
|
specification_version: 4
|
222
223
|
summary: A Ruby SCALE Codec Library, and, Substrate RPC Client
|
@@ -1,263 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './type_exp'
|
4
|
-
require_relative '../types'
|
5
|
-
|
6
|
-
# rubocop:disable all
|
7
|
-
module ScaleRb
|
8
|
-
module Metadata
|
9
|
-
class Registry
|
10
|
-
include Types
|
11
|
-
|
12
|
-
# Map name to index of type in `types` array
|
13
|
-
# % lookup :: String -> Integer
|
14
|
-
attr_reader :lookup
|
15
|
-
|
16
|
-
# % keys :: Integer -> String
|
17
|
-
attr_reader :keys
|
18
|
-
|
19
|
-
# % types :: Array<PortableType>
|
20
|
-
attr_reader :types
|
21
|
-
|
22
|
-
attr_reader :old_types
|
23
|
-
|
24
|
-
# % initialize :: Hash<Symbol, Any> -> void
|
25
|
-
def initialize(old_types)
|
26
|
-
@old_types = old_types
|
27
|
-
@lookup = {}
|
28
|
-
@keys = {}
|
29
|
-
@types = []
|
30
|
-
|
31
|
-
build()
|
32
|
-
end
|
33
|
-
|
34
|
-
def build()
|
35
|
-
@old_types.keys.each do |name|
|
36
|
-
use(name.to_s)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def [](index)
|
41
|
-
@types[index]
|
42
|
-
end
|
43
|
-
|
44
|
-
def inspect
|
45
|
-
"registry(#{@types.length} types)"
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_s
|
49
|
-
@types.map.with_index do |type, index|
|
50
|
-
"#{@keys[index]} => #{type.to_s}"
|
51
|
-
end.join("\n")
|
52
|
-
end
|
53
|
-
|
54
|
-
# % use :: String -> Integer
|
55
|
-
def use(old_type_exp)
|
56
|
-
raise "Empty old_type_exp: #{old_type_exp}" if old_type_exp.nil? || old_type_exp.strip == ''
|
57
|
-
|
58
|
-
ast_type = TypeExp.parse(old_type_exp)
|
59
|
-
raise "No AST type for #{old_type_exp}" if ast_type.nil?
|
60
|
-
|
61
|
-
key = ast_type.to_s
|
62
|
-
ti = lookup[key]
|
63
|
-
return ti if ti
|
64
|
-
|
65
|
-
ti = @types.length
|
66
|
-
@types[ti] = "Placeholder"
|
67
|
-
@lookup[key] = ti
|
68
|
-
@keys[ti] = key
|
69
|
-
@types[ti] = build_portable_type(ast_type)
|
70
|
-
ti
|
71
|
-
end
|
72
|
-
|
73
|
-
# % build_portable_type :: NamedType | ArrayType | TupleType -> PortableType
|
74
|
-
# __ :build_portable_type, { ast_type: TypedArray[TypeExp::ArrayType | TypeExp::TupleType | TypeExp::NamedType] } => PortableType
|
75
|
-
def build_portable_type(ast_type)
|
76
|
-
case ast_type
|
77
|
-
when TypeExp::ArrayType
|
78
|
-
ArrayType.new(use(ast_type.item), ast_type.len, registry: self)
|
79
|
-
when TypeExp::TupleType
|
80
|
-
TupleType.new(ast_type.params.map { |param| use(param) })
|
81
|
-
when TypeExp::NamedType
|
82
|
-
build_portable_type_from_named_type(ast_type)
|
83
|
-
else
|
84
|
-
raise "Unknown type: #{ast_type.class}"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# % build_portable_type_from_named_type :: NamedType -> PortableType
|
89
|
-
def build_portable_type_from_named_type(named_type)
|
90
|
-
name = named_type.name
|
91
|
-
params = named_type.params
|
92
|
-
|
93
|
-
definition = @old_types[name.to_sym]
|
94
|
-
return build_from_definition(name, definition) if definition
|
95
|
-
|
96
|
-
primitive = as_primitive(name)
|
97
|
-
return primitive if primitive
|
98
|
-
|
99
|
-
case name
|
100
|
-
when 'Vec'
|
101
|
-
item_index = use(params[0].to_s)
|
102
|
-
SequenceType.new(type: item_index, registry: self)
|
103
|
-
when 'Option'
|
104
|
-
item_index = use(params[0].to_s)
|
105
|
-
VariantType.option(item_index, self)
|
106
|
-
when 'Result'
|
107
|
-
ok_index = use(params[0].to_s)
|
108
|
-
err_index = use(params[1].to_s)
|
109
|
-
VariantType.result(ok_index, err_index, self)
|
110
|
-
when 'Compact'
|
111
|
-
# item_index = use(params[0].to_s)
|
112
|
-
# CompactType.new(type: item_index, registry: self)
|
113
|
-
CompactType.new
|
114
|
-
when 'Null'
|
115
|
-
UnitType.new
|
116
|
-
else
|
117
|
-
raise "Unknown type: #{name}"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
# % as_primitive :: String -> PrimitiveType | nil
|
122
|
-
def as_primitive(name)
|
123
|
-
case name.downcase
|
124
|
-
when /^i\d+$/
|
125
|
-
PrimitiveType.new(primitive: "I#{name[1..]}".to_sym)
|
126
|
-
when /^u\d+$/
|
127
|
-
PrimitiveType.new(primitive: "U#{name[1..]}".to_sym)
|
128
|
-
when /^bool$/
|
129
|
-
PrimitiveType.new(primitive: :Bool)
|
130
|
-
when /^str$/, /^text$/
|
131
|
-
PrimitiveType.new(primitive: :Str)
|
132
|
-
else
|
133
|
-
nil
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# % build_from_definition :: String -> OldTypeDefinition -> PortableType | TypeAlias
|
138
|
-
#
|
139
|
-
# type OldTypeDefinition = String | OldEnumDefinition | OldStructDefinition
|
140
|
-
# type OldEnumDefinition = {
|
141
|
-
# _enum: String[] | Hash<Symbol, Any>,
|
142
|
-
# }
|
143
|
-
# type OldStructDefinition = {
|
144
|
-
# _struct: Hash<Symbol, Any>
|
145
|
-
# }
|
146
|
-
def build_from_definition(name, definition) # rubocop:disable Metrics/MethodLength
|
147
|
-
case definition
|
148
|
-
when String
|
149
|
-
# TypeAlias.new(name, use(definition))
|
150
|
-
alias_type_id = use(definition)
|
151
|
-
# p "alias_type_id: #{alias_type_id}"
|
152
|
-
types[alias_type_id]
|
153
|
-
when Hash
|
154
|
-
if definition[:_enum]
|
155
|
-
_build_portable_type_from_enum_definition(definition)
|
156
|
-
elsif definition[:_set]
|
157
|
-
raise 'Sets are not supported'
|
158
|
-
else
|
159
|
-
_build_portable_type_from_struct_definition(definition)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
private
|
165
|
-
|
166
|
-
def _indexed_enum?(definition)
|
167
|
-
definition[:_enum].is_a?(::Hash) && definition[:_enum].values.all? { |value| value.is_a?(::Integer) }
|
168
|
-
end
|
169
|
-
|
170
|
-
# % _build_portable_type_from_enum_definition :: Hash<Symbol, Any> -> VariantType
|
171
|
-
def _build_portable_type_from_enum_definition(definition)
|
172
|
-
variants =
|
173
|
-
if definition[:_enum].is_a?(::Array)
|
174
|
-
# Simple array enum:
|
175
|
-
# {
|
176
|
-
# _enum: ['A', 'B', 'C']
|
177
|
-
# }
|
178
|
-
definition[:_enum].map.with_index do |variant_name, index|
|
179
|
-
SimpleVariant.new(name: variant_name.to_sym, index:)
|
180
|
-
end
|
181
|
-
elsif definition[:_enum].is_a?(::Hash)
|
182
|
-
if _indexed_enum?(definition)
|
183
|
-
# Indexed enum:
|
184
|
-
# {
|
185
|
-
# _enum: {
|
186
|
-
# Variant1: 0,
|
187
|
-
# Variant2: 1,
|
188
|
-
# Variant3: 2
|
189
|
-
# }
|
190
|
-
# }
|
191
|
-
definition[:_enum].map do |variant_name, index|
|
192
|
-
SimpleVariant.new(name: variant_name, index:)
|
193
|
-
end
|
194
|
-
else
|
195
|
-
# Mixed enum:
|
196
|
-
# {
|
197
|
-
# _enum: {
|
198
|
-
# A: 'u32',
|
199
|
-
# B: {a: 'u32', b: 'u32'},
|
200
|
-
# C: null,
|
201
|
-
# D: ['u32', 'u32']
|
202
|
-
# }
|
203
|
-
# }
|
204
|
-
definition[:_enum].map.with_index do |(variant_name, variant_def), index|
|
205
|
-
case variant_def
|
206
|
-
when ::String
|
207
|
-
TupleVariant.new(
|
208
|
-
name: variant_name,
|
209
|
-
index:,
|
210
|
-
tuple: TupleType.new(
|
211
|
-
tuple: [use(variant_def)],
|
212
|
-
registry: self
|
213
|
-
),
|
214
|
-
)
|
215
|
-
when ::Array
|
216
|
-
TupleVariant.new(
|
217
|
-
name: variant_name,
|
218
|
-
index:,
|
219
|
-
tuple: TupleType.new(
|
220
|
-
tuple: variant_def.map { |field_type| use(field_type) },
|
221
|
-
registry: self
|
222
|
-
)
|
223
|
-
)
|
224
|
-
when ::Hash
|
225
|
-
StructVariant.new(
|
226
|
-
name: variant_name,
|
227
|
-
index:,
|
228
|
-
struct: StructType.new(
|
229
|
-
fields: variant_def.map do |field_name, field_type|
|
230
|
-
Field.new(name: field_name.to_s, type: use(field_type))
|
231
|
-
end,
|
232
|
-
registry: self
|
233
|
-
)
|
234
|
-
)
|
235
|
-
else
|
236
|
-
raise "Unknown variant type for #{variant_name}: #{variant_def.class}"
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
VariantType.new(variants:, registry: self)
|
242
|
-
end
|
243
|
-
|
244
|
-
# % _build_portable_type_from_struct_definition :: Hash<Symbol, Any> -> StructType
|
245
|
-
def _build_portable_type_from_struct_definition(definition)
|
246
|
-
fields = definition.map do |field_name, field_type|
|
247
|
-
Field.new(name: field_name.to_s, type: use(field_type))
|
248
|
-
end
|
249
|
-
StructType.new(fields:, registry: self)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
# require_relative '../../metadata/metadata'
|
256
|
-
|
257
|
-
# begin
|
258
|
-
# registry = ScaleRb::Metadata::Registry.new ScaleRb::Metadata::TYPES
|
259
|
-
# puts registry
|
260
|
-
# rescue StandardError => e
|
261
|
-
# puts e.message
|
262
|
-
# puts e.backtrace.join("\n")
|
263
|
-
# end
|
@@ -1,286 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ScaleRb
|
4
|
-
module Metadata
|
5
|
-
module TypeExp
|
6
|
-
class Tokenizer
|
7
|
-
attr_reader :tokens, :index
|
8
|
-
|
9
|
-
# % tokenize :: String -> [String]
|
10
|
-
def initialize(type_exp)
|
11
|
-
@tokens = tokenize(type_exp)
|
12
|
-
@index = 0
|
13
|
-
end
|
14
|
-
|
15
|
-
# % next_token :: -> String
|
16
|
-
def next_token
|
17
|
-
token = @tokens[@index]
|
18
|
-
@index += 1
|
19
|
-
token
|
20
|
-
end
|
21
|
-
|
22
|
-
# % peek_token :: -> String
|
23
|
-
def peek_token
|
24
|
-
@tokens[@index]
|
25
|
-
end
|
26
|
-
|
27
|
-
# % eof? :: -> Bool
|
28
|
-
def eof?
|
29
|
-
@index >= @tokens.length
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def tokenize(type_exp)
|
35
|
-
tokens = []
|
36
|
-
current_token = ''
|
37
|
-
|
38
|
-
type_exp.each_char do |char|
|
39
|
-
case char
|
40
|
-
when /[a-zA-Z0-9_]/
|
41
|
-
current_token += char
|
42
|
-
when ':', '<', '>', '(', ')', '[', ']', ',', ';', '&', "'"
|
43
|
-
tokens << current_token unless current_token.empty?
|
44
|
-
if char == ':' && tokens.last == ':'
|
45
|
-
tokens[-1] = '::'
|
46
|
-
else
|
47
|
-
tokens << char
|
48
|
-
end
|
49
|
-
current_token = ''
|
50
|
-
when /\s/
|
51
|
-
tokens << current_token unless current_token.empty?
|
52
|
-
current_token = ''
|
53
|
-
else
|
54
|
-
raise abort
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
tokens << current_token unless current_token.empty?
|
59
|
-
tokens
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class NamedType
|
64
|
-
attr_reader :name, :params
|
65
|
-
|
66
|
-
def initialize(name, params)
|
67
|
-
@name = name
|
68
|
-
@params = params
|
69
|
-
end
|
70
|
-
|
71
|
-
def to_s
|
72
|
-
params.empty? ? name : "#{name}<#{params.map(&:to_s).join(', ')}>"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
class ArrayType
|
77
|
-
attr_reader :item, :len
|
78
|
-
|
79
|
-
def initialize(item, len)
|
80
|
-
@item = item
|
81
|
-
@len = len
|
82
|
-
end
|
83
|
-
|
84
|
-
def to_s
|
85
|
-
"[#{item}; #{len}]"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
class TupleType
|
90
|
-
attr_reader :params
|
91
|
-
|
92
|
-
def initialize(params)
|
93
|
-
@params = params
|
94
|
-
end
|
95
|
-
|
96
|
-
def to_s
|
97
|
-
"(#{params.map(&:to_s).join(', ')})"
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# % print :: NamedType | ArrayType | TupleType -> String
|
102
|
-
def self.print(type)
|
103
|
-
type.to_s
|
104
|
-
end
|
105
|
-
|
106
|
-
# % parse :: String -> NamedType | ArrayType | TupleType
|
107
|
-
def self.parse(type_exp)
|
108
|
-
TypeExpParser.new(type_exp).parse
|
109
|
-
end
|
110
|
-
|
111
|
-
class TypeExpParser
|
112
|
-
def initialize(type_exp)
|
113
|
-
@type_exp = type_exp
|
114
|
-
@tokenizer = Tokenizer.new(type_exp)
|
115
|
-
@current_token = @tokenizer.next_token
|
116
|
-
end
|
117
|
-
|
118
|
-
def parse
|
119
|
-
build_type
|
120
|
-
end
|
121
|
-
|
122
|
-
private
|
123
|
-
|
124
|
-
# Consume and return the current token, or nil if it doesn't equal the expected token.
|
125
|
-
def expect(token)
|
126
|
-
return unless @current_token == token
|
127
|
-
|
128
|
-
current_token = @current_token
|
129
|
-
@current_token = @tokenizer.next_token
|
130
|
-
current_token
|
131
|
-
end
|
132
|
-
|
133
|
-
def expect!(token)
|
134
|
-
expect(token) || raise("Expected #{token}, got #{@current_token}")
|
135
|
-
end
|
136
|
-
|
137
|
-
# Consume and return the current token if it matches the expected regex pattern.
|
138
|
-
def expect_regex(pattern)
|
139
|
-
return unless pattern.match?(@current_token)
|
140
|
-
|
141
|
-
current_token = @current_token
|
142
|
-
@current_token = @tokenizer.next_token
|
143
|
-
current_token
|
144
|
-
end
|
145
|
-
|
146
|
-
def expect_regex!(pattern)
|
147
|
-
expect_regex(pattern) || raise("Expected current token matching #{pattern.inspect}, got #{@current_token}")
|
148
|
-
end
|
149
|
-
|
150
|
-
# Consume and return a natural number (integer) if the current token matches.
|
151
|
-
def expect_nat
|
152
|
-
expect_regex(/^\d+$/)&.to_i
|
153
|
-
end
|
154
|
-
|
155
|
-
def expect_nat!
|
156
|
-
expect_nat || raise("Expected natural number, got #{@current_token}")
|
157
|
-
end
|
158
|
-
|
159
|
-
def expect_name
|
160
|
-
expect_regex(/^[a-zA-Z]\w*$/)
|
161
|
-
end
|
162
|
-
|
163
|
-
def expect_name!
|
164
|
-
expect_name || raise("Expected name, got #{@current_token}")
|
165
|
-
end
|
166
|
-
|
167
|
-
def list(sep, &block)
|
168
|
-
result = []
|
169
|
-
item = block.call
|
170
|
-
return result if item.nil?
|
171
|
-
|
172
|
-
result << item
|
173
|
-
while expect(sep)
|
174
|
-
item = block.call
|
175
|
-
break if item.nil? # (A, B,)
|
176
|
-
|
177
|
-
result << item
|
178
|
-
end
|
179
|
-
result
|
180
|
-
end
|
181
|
-
|
182
|
-
def build_tuple_type
|
183
|
-
return nil unless expect('(')
|
184
|
-
|
185
|
-
params = list(',') { build_type }
|
186
|
-
expect!(')')
|
187
|
-
|
188
|
-
TupleType.new(params)
|
189
|
-
end
|
190
|
-
|
191
|
-
# [u8; 16; H128]
|
192
|
-
# [u8; 16]
|
193
|
-
def build_array_type
|
194
|
-
return nil unless expect('[')
|
195
|
-
|
196
|
-
item = build_type
|
197
|
-
raise "Expected array item, got #{@current_token}" if item.nil?
|
198
|
-
|
199
|
-
expect!(';')
|
200
|
-
len = expect_nat!
|
201
|
-
|
202
|
-
# [u8; 16; H128]
|
203
|
-
if expect(';')
|
204
|
-
expect_name! # Just consume the name
|
205
|
-
end
|
206
|
-
|
207
|
-
expect!(']')
|
208
|
-
ArrayType.new(item, len)
|
209
|
-
end
|
210
|
-
|
211
|
-
def build_named_type
|
212
|
-
name = nil
|
213
|
-
trait = nil
|
214
|
-
item = nil
|
215
|
-
|
216
|
-
if expect('<')
|
217
|
-
# Handle trait syntax: <T::Trait as OtherTrait>::Type
|
218
|
-
# name trait item
|
219
|
-
# '<T::InherentOfflineReport as InherentOfflineReport>::Inherent' -> 'InherentOfflineReport'
|
220
|
-
# '<T::Balance as HasCompact>' -> 'Compact<Balance>'
|
221
|
-
# '<T as Trait<I>>::Proposal' -> 'Proposal'
|
222
|
-
name = build_named_type.name
|
223
|
-
expect!('as')
|
224
|
-
trait = build_named_type.name
|
225
|
-
expect!('>')
|
226
|
-
else
|
227
|
-
name = expect_name
|
228
|
-
return if name.nil?
|
229
|
-
end
|
230
|
-
|
231
|
-
# Consume the :: and get the next name
|
232
|
-
item = expect_name while expect('::')
|
233
|
-
|
234
|
-
# Handle special cases
|
235
|
-
# From subsquid's code. But where are these coming from?
|
236
|
-
if name == 'InherentOfflineReport' && name == trait && item == 'Inherent'
|
237
|
-
# Do nothing
|
238
|
-
elsif name == 'exec' && item == 'StorageKey'
|
239
|
-
name = 'ContractStorageKey'
|
240
|
-
elsif name == 'Lookup' && item == 'Source'
|
241
|
-
name = 'LookupSource'
|
242
|
-
elsif name == 'Lookup' && item == 'Target'
|
243
|
-
name = 'LookupTarget'
|
244
|
-
elsif item
|
245
|
-
# '<T::Balance as HasCompact>::Item' will raise error
|
246
|
-
raise "Expected item, got #{item}" if trait == 'HasCompact'
|
247
|
-
|
248
|
-
name = item
|
249
|
-
elsif trait == 'HasCompact' # '<T::Balance as HasCompact>'
|
250
|
-
return NamedType.new('Compact', [NamedType.new(name, [])])
|
251
|
-
end
|
252
|
-
|
253
|
-
NamedType.new(name, type_parameters)
|
254
|
-
end
|
255
|
-
|
256
|
-
def type_parameters
|
257
|
-
if expect('<')
|
258
|
-
params = list(',') { expect_nat || build_type }
|
259
|
-
expect!('>')
|
260
|
-
else
|
261
|
-
params = []
|
262
|
-
end
|
263
|
-
|
264
|
-
params
|
265
|
-
end
|
266
|
-
|
267
|
-
# &[u8]
|
268
|
-
# &'static [u8]
|
269
|
-
def build_pointer_bytes
|
270
|
-
return nil unless expect('&') # &
|
271
|
-
|
272
|
-
expect("'") && expect!('static')
|
273
|
-
expect!('[')
|
274
|
-
expect!('u8')
|
275
|
-
expect!(']')
|
276
|
-
NamedType.new('Vec', [NamedType.new('u8', [])])
|
277
|
-
end
|
278
|
-
|
279
|
-
# % build_type :: TupleType | ArrayType | NamedType
|
280
|
-
def build_type
|
281
|
-
build_tuple_type || build_array_type || build_named_type || build_pointer_bytes
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|