scale.rb 0.2.17 → 0.3.1
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/.gitignore +1 -0
- data/Cargo.lock +8 -4
- data/Cargo.toml +2 -3
- data/Dockerfile +4 -1
- data/Gemfile.lock +23 -21
- data/README.md +44 -1
- data/Rakefile +6 -0
- data/exe/scale +49 -0
- data/lib/helper.rb +19 -4
- data/lib/metadata/metadata.rb +27 -17
- data/lib/metadata/metadata_v0.rb +24 -20
- data/lib/metadata/metadata_v1.rb +13 -9
- data/lib/metadata/metadata_v10.rb +2 -2
- data/lib/metadata/metadata_v11.rb +2 -2
- data/lib/metadata/metadata_v12.rb +9 -8
- data/lib/metadata/metadata_v13.rb +161 -0
- data/lib/metadata/metadata_v2.rb +2 -2
- data/lib/metadata/metadata_v3.rb +2 -2
- data/lib/metadata/metadata_v4.rb +21 -11
- data/lib/metadata/metadata_v5.rb +21 -11
- data/lib/metadata/metadata_v6.rb +9 -9
- data/lib/metadata/metadata_v7.rb +26 -15
- data/lib/metadata/metadata_v8.rb +9 -9
- data/lib/metadata/metadata_v9.rb +2 -2
- data/lib/scale.rb +40 -339
- data/lib/scale/base.rb +175 -93
- data/lib/scale/block.rb +10 -10
- data/lib/scale/trie.rb +1 -1
- data/lib/scale/types.rb +139 -40
- data/lib/scale/version.rb +1 -1
- data/lib/scale_bytes.rb +63 -0
- data/lib/substrate_client.rb +11 -8
- data/lib/type_builder.rb +280 -0
- data/lib/type_registry.rb +91 -0
- data/lib/type_registry/crab.json +676 -595
- data/lib/type_registry/darwinia.json +730 -554
- data/lib/type_registry/default.json +3 -2
- data/lib/type_registry/pangolin.json +771 -0
- data/scale.gemspec +1 -0
- data/scripts/mmr_root_to_sign.rb +10 -0
- data/src/lib.rs +80 -25
- metadata +25 -10
- data/lib/type_registry/edgeware.json +0 -124
- data/lib/type_registry/joystream.json +0 -49
- data/lib/type_registry/kulupu.json +0 -15
- data/lib/type_registry/plasm.json +0 -89
- data/lib/type_registry/robonomics.json +0 -39
- data/lib/type_registry/westend.json +0 -63
- data/src/storage_key.rs +0 -41
data/lib/metadata/metadata_v9.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Scale
|
2
2
|
module Types
|
3
3
|
class MetadataV9
|
4
|
-
include
|
4
|
+
include Base
|
5
5
|
attr_accessor :call_index, :event_index
|
6
6
|
|
7
7
|
def initialize(value)
|
@@ -11,7 +11,7 @@ module Scale
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.decode(scale_bytes)
|
14
|
-
modules = Scale::Types.
|
14
|
+
modules = Scale::Types.get("Vec<MetadataV8Module>").decode(scale_bytes).value
|
15
15
|
|
16
16
|
value = {
|
17
17
|
magicNumber: 1_635_018_093,
|
data/lib/scale.rb
CHANGED
@@ -5,6 +5,11 @@ require "common"
|
|
5
5
|
require "json"
|
6
6
|
require "singleton"
|
7
7
|
|
8
|
+
require "scale_bytes"
|
9
|
+
|
10
|
+
require "type_registry"
|
11
|
+
require "type_builder"
|
12
|
+
|
8
13
|
require "scale/base"
|
9
14
|
require "scale/types"
|
10
15
|
require "scale/block"
|
@@ -24,361 +29,36 @@ require "metadata/metadata_v9"
|
|
24
29
|
require "metadata/metadata_v10"
|
25
30
|
require "metadata/metadata_v11"
|
26
31
|
require "metadata/metadata_v12"
|
32
|
+
require "metadata/metadata_v13"
|
27
33
|
|
28
34
|
require "substrate_client"
|
29
35
|
require "logger"
|
30
36
|
require "helper"
|
31
37
|
|
32
|
-
class String
|
33
|
-
def upcase_first
|
34
|
-
self.sub(/\S/, &:upcase)
|
35
|
-
end
|
36
|
-
|
37
|
-
def camelize2
|
38
|
-
self.split('_').collect(&:upcase_first).join
|
39
|
-
end
|
40
|
-
|
41
|
-
def underscore2
|
42
|
-
self.gsub(/::/, '/').
|
43
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
44
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
45
|
-
tr("-", "_").
|
46
|
-
downcase
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
38
|
module Scale
|
51
|
-
class
|
52
|
-
|
53
|
-
class
|
54
|
-
|
55
|
-
|
56
|
-
# init by load, and will not change
|
57
|
-
attr_reader :spec_name, :types
|
58
|
-
attr_reader :versioning, :custom_types # optional
|
59
|
-
|
60
|
-
# will change by different spec version
|
61
|
-
attr_accessor :spec_version # optional
|
62
|
-
attr_accessor :metadata
|
63
|
-
|
64
|
-
def load(spec_name: nil, custom_types: nil)
|
65
|
-
@spec_name = nil
|
66
|
-
@types = nil
|
67
|
-
@versioning = nil
|
68
|
-
@custom_types = nil
|
39
|
+
class ScaleError < StandardError; end
|
40
|
+
class TypeBuildError < ScaleError; end
|
41
|
+
class BadDataError < ScaleError; end
|
42
|
+
class TypeRegistryNotLoadYet < ScaleError; end
|
43
|
+
class StorageInputTypeError < ScaleError; end
|
69
44
|
|
70
|
-
|
45
|
+
module Types
|
46
|
+
class << self
|
47
|
+
attr_accessor :debug, :logger
|
48
|
+
end
|
71
49
|
|
72
|
-
|
50
|
+
def self.check_types
|
51
|
+
TypeRegistry.instance.all_types.keys.each do |key|
|
73
52
|
begin
|
74
|
-
|
75
|
-
spec_types, @versioning, @spec_version = load_chain_spec_types(spec_name)
|
76
|
-
@types = default_types.merge(spec_types)
|
53
|
+
type = self.get(key)
|
77
54
|
rescue => ex
|
78
|
-
puts "
|
79
|
-
@types = default_types
|
55
|
+
puts "[[ERROR]] #{key}: #{ex}"
|
80
56
|
end
|
81
|
-
else
|
82
|
-
@spec_name = "default"
|
83
|
-
@types = default_types
|
84
57
|
end
|
85
|
-
|
86
|
-
self.custom_types = custom_types
|
87
58
|
true
|
88
59
|
end
|
89
60
|
|
90
|
-
def get(type_name)
|
91
|
-
raise "Types not loaded" if @types.nil?
|
92
|
-
|
93
|
-
all_types = {}.merge(@types)
|
94
|
-
|
95
|
-
if @spec_version && @versioning
|
96
|
-
@versioning.each do |item|
|
97
|
-
if @spec_version >= item["runtime_range"][0] &&
|
98
|
-
( item["runtime_range"][1].nil? || @spec_version <= item["runtime_range"][1] )
|
99
|
-
all_types.merge!(item["types"])
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
all_types.merge!(@custom_types) if @custom_types
|
105
|
-
|
106
|
-
type = type_traverse(type_name, all_types)
|
107
|
-
|
108
|
-
Scale::Types.constantize(type)
|
109
|
-
end
|
110
|
-
|
111
|
-
def custom_types=(custom_types)
|
112
|
-
@custom_types = custom_types.stringify_keys if (not custom_types.nil?) && custom_types.class.name == "Hash"
|
113
|
-
end
|
114
|
-
|
115
|
-
private
|
116
|
-
|
117
|
-
def load_chain_spec_types(spec_name)
|
118
|
-
file = File.join File.expand_path("../..", __FILE__), "lib", "type_registry", "#{spec_name}.json"
|
119
|
-
json_string = File.open(file).read
|
120
|
-
json = JSON.parse(json_string)
|
121
|
-
|
122
|
-
runtime_id = json["runtime_id"]
|
123
|
-
|
124
|
-
[json["types"], json["versioning"], runtime_id]
|
125
|
-
end
|
126
|
-
|
127
|
-
def type_traverse(type, types)
|
128
|
-
type = rename(type) if type.class == ::String
|
129
|
-
if types.has_key?(type) && types[type] != type
|
130
|
-
type_traverse(types[type], types)
|
131
|
-
else
|
132
|
-
type
|
133
|
-
end
|
134
|
-
end
|
135
61
|
end
|
136
|
-
|
137
|
-
# TODO: == implement
|
138
|
-
|
139
|
-
class Bytes
|
140
|
-
attr_reader :data, :bytes
|
141
|
-
attr_reader :offset
|
142
|
-
|
143
|
-
def initialize(data)
|
144
|
-
if (data.class == Array) && data.is_byte_array?
|
145
|
-
@bytes = data
|
146
|
-
elsif (data.class == String) && data.start_with?("0x") && (data.length % 2 == 0)
|
147
|
-
arr = data[2..].scan(/../).map(&:hex)
|
148
|
-
@bytes = arr
|
149
|
-
else
|
150
|
-
raise "Provided data is not valid"
|
151
|
-
end
|
152
|
-
|
153
|
-
@data = data
|
154
|
-
@offset = 0
|
155
|
-
end
|
156
|
-
|
157
|
-
def reset_offset
|
158
|
-
@offset = 0
|
159
|
-
end
|
160
|
-
|
161
|
-
def get_next_bytes(length)
|
162
|
-
result = @bytes[@offset...@offset + length]
|
163
|
-
if result.length < length
|
164
|
-
str = @data[(2 + @offset * 2)..]
|
165
|
-
str = str.length > 40 ? (str[0...40]).to_s + "..." : str
|
166
|
-
raise "No enough data: #{str}, expect length: #{length}, but #{result.length}"
|
167
|
-
end
|
168
|
-
@offset += length
|
169
|
-
result
|
170
|
-
rescue RangeError => ex
|
171
|
-
puts "length: #{length}"
|
172
|
-
puts ex.message
|
173
|
-
puts ex.backtrace
|
174
|
-
end
|
175
|
-
|
176
|
-
def get_remaining_bytes
|
177
|
-
@bytes[offset..]
|
178
|
-
end
|
179
|
-
|
180
|
-
def to_hex_string
|
181
|
-
@bytes.bytes_to_hex
|
182
|
-
end
|
183
|
-
|
184
|
-
def to_bin_string
|
185
|
-
@bytes.bytes_to_bin
|
186
|
-
end
|
187
|
-
|
188
|
-
def to_ascii
|
189
|
-
@bytes[0...offset].pack("C*") + "<================================>" + @bytes[offset..].pack("C*")
|
190
|
-
end
|
191
|
-
|
192
|
-
def ==(other)
|
193
|
-
bytes == other.bytes && offset == other.offset
|
194
|
-
end
|
195
|
-
|
196
|
-
def to_s
|
197
|
-
green(@bytes[0...offset].bytes_to_hex) + yellow(@bytes[offset..].bytes_to_hex[2..])
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
class TypesLoader
|
202
|
-
def self.load(filename)
|
203
|
-
path = File.join File.dirname(__FILE__), "types", filename
|
204
|
-
content = File.open(path).read
|
205
|
-
result = JSON.parse content
|
206
|
-
|
207
|
-
types = result["default"]
|
208
|
-
types.each do |name, body|
|
209
|
-
if body.class == String
|
210
|
-
target_type = "Scale::Types::#{body}"
|
211
|
-
klass = Class.new(target_type.constantize2) do
|
212
|
-
end
|
213
|
-
elsif body.class == Hash
|
214
|
-
if body["type"] == "struct"
|
215
|
-
struct_params = {}
|
216
|
-
body["type_mapping"].each do |mapping|
|
217
|
-
struct_params[mapping[0].to_sym] = mapping[1]
|
218
|
-
end
|
219
|
-
klass = Class.new do
|
220
|
-
end
|
221
|
-
klass.send(:include, Scale::Types::Struct)
|
222
|
-
klass.send(:items, struct_params)
|
223
|
-
Scale::Types.const_set name, klass
|
224
|
-
elsif body["type"] = "enum"
|
225
|
-
klass = Class.new do
|
226
|
-
end
|
227
|
-
klass.send(:include, Scale::Types::Enum)
|
228
|
-
if body["type_mapping"]
|
229
|
-
struct_params = {}
|
230
|
-
body["type_mapping"].each do |mapping|
|
231
|
-
struct_params[mapping[0].to_sym] = mapping[1]
|
232
|
-
end
|
233
|
-
klass.send(:items, struct_params)
|
234
|
-
else
|
235
|
-
klass.send(:values, body["value_list"])
|
236
|
-
end
|
237
|
-
Scale::Types.const_set name, klass
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
module Types
|
245
|
-
def self.list
|
246
|
-
TypeRegistry.instance.types
|
247
|
-
end
|
248
|
-
|
249
|
-
def self.get(type_name)
|
250
|
-
TypeRegistry.instance.get(type_name)
|
251
|
-
end
|
252
|
-
|
253
|
-
def self.constantize(type)
|
254
|
-
if type.class == ::String
|
255
|
-
type_of(type.strip)
|
256
|
-
else
|
257
|
-
if type["type"] == "enum" && type.has_key?("type_mapping")
|
258
|
-
type_of("Enum", type["type_mapping"].to_h)
|
259
|
-
elsif type["type"] == "enum" && type.has_key?("value_list")
|
260
|
-
type_of("Enum", type["value_list"])
|
261
|
-
elsif type["type"] == "struct"
|
262
|
-
type_of("Struct", type["type_mapping"].to_h)
|
263
|
-
elsif type["type"] == "set"
|
264
|
-
type_of("Set", type["value_list"])
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
def self.type_of(type_string, values = nil)
|
270
|
-
if type_string.end_with?(">")
|
271
|
-
type_strs = type_string.scan(/^([^<]*)<(.+)>$/).first
|
272
|
-
type_str = type_strs.first
|
273
|
-
inner_type_str = type_strs.last
|
274
|
-
|
275
|
-
if type_str == "Vec" || type_str == "Option"
|
276
|
-
klass = Class.new do
|
277
|
-
include Scale::Types.type_of(type_str)
|
278
|
-
inner_type inner_type_str
|
279
|
-
end
|
280
|
-
name = "#{type_str}<#{inner_type_str.camelize2}>_#{klass.object_id}"
|
281
|
-
Scale::Types.const_set fix(name), klass
|
282
|
-
else
|
283
|
-
raise "#{type_str} not support inner type: #{type_string}"
|
284
|
-
end
|
285
|
-
elsif type_string.start_with?("(") && type_string.end_with?(")") # tuple
|
286
|
-
# TODO: add nested tuple support
|
287
|
-
types_with_inner_type = type_string[1...-1].scan(/([A-Za-z]+<[^>]*>)/).first
|
288
|
-
|
289
|
-
types_with_inner_type&.each do |type_str|
|
290
|
-
new_type_str = type_str.tr(",", ";")
|
291
|
-
type_string = type_string.gsub(type_str, new_type_str)
|
292
|
-
end
|
293
|
-
|
294
|
-
type_strs = type_string[1...-1].split(",").map do |type_str|
|
295
|
-
type_str.strip.tr(";", ",")
|
296
|
-
end
|
297
|
-
|
298
|
-
klass = Class.new do
|
299
|
-
include Scale::Types::Tuple
|
300
|
-
inner_types *type_strs
|
301
|
-
end
|
302
|
-
name = "Tuple_Of_#{type_strs.map(&:camelize2).join("_")}_#{klass.object_id}"
|
303
|
-
Scale::Types.const_set fix(name), klass
|
304
|
-
else
|
305
|
-
if type_string == "Enum"
|
306
|
-
# TODO: combine values to items
|
307
|
-
klass = Class.new do
|
308
|
-
include Scale::Types::Enum
|
309
|
-
if values.class == ::Hash
|
310
|
-
items values
|
311
|
-
else
|
312
|
-
values(*values)
|
313
|
-
end
|
314
|
-
end
|
315
|
-
name = values.class == ::Hash ? values.values.map(&:camelize2).join("_") : values.map(&:camelize2).join("_")
|
316
|
-
name = "Enum_Of_#{name}_#{klass.object_id}"
|
317
|
-
Scale::Types.const_set fix(name), klass
|
318
|
-
elsif type_string == "Struct"
|
319
|
-
klass = Class.new do
|
320
|
-
include Scale::Types::Struct
|
321
|
-
items values
|
322
|
-
end
|
323
|
-
name = "Struct_Of_#{values.values.map(&:camelize2).join("_")}_#{klass.object_id}"
|
324
|
-
Scale::Types.const_set fix(name), klass
|
325
|
-
elsif type_string == "Set"
|
326
|
-
klass = Class.new do
|
327
|
-
include Scale::Types::Set
|
328
|
-
items values, 1
|
329
|
-
end
|
330
|
-
name = "Set_Of_#{values.keys.map(&:camelize2).join("_")}_#{klass.object_id}"
|
331
|
-
Scale::Types.const_set fix(name), klass
|
332
|
-
else
|
333
|
-
type_name = (type_string.start_with?("Scale::Types::") ? type_string : "Scale::Types::#{type_string}")
|
334
|
-
begin
|
335
|
-
type_name.constantize2
|
336
|
-
rescue NameError => e
|
337
|
-
puts "#{type_string} is not defined"
|
338
|
-
end
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
end
|
345
|
-
|
346
|
-
def fix(name)
|
347
|
-
name
|
348
|
-
.gsub("<", "˂").gsub(">", "˃")
|
349
|
-
.gsub("(", "⁽").gsub(")", "⁾")
|
350
|
-
.gsub(" ", "").gsub(",", "‚")
|
351
|
-
.gsub(":", "։")
|
352
|
-
end
|
353
|
-
|
354
|
-
def rename(type)
|
355
|
-
type = type.gsub("T::", "")
|
356
|
-
.gsub("<T>", "")
|
357
|
-
.gsub("<T as Trait>::", "")
|
358
|
-
.delete("\n")
|
359
|
-
.gsub("EventRecord<Event, Hash>", "EventRecord")
|
360
|
-
.gsub(/(u)(\d+)/, 'U\2')
|
361
|
-
return "Bool" if type == "bool"
|
362
|
-
return "Null" if type == "()"
|
363
|
-
return "String" if type == "Vec<u8>"
|
364
|
-
return "Compact" if type == "Compact<u32>" || type == "Compact<U32>"
|
365
|
-
return "Address" if type == "<Lookup as StaticLookup>::Source"
|
366
|
-
return "Vec<Address>" if type == "Vec<<Lookup as StaticLookup>::Source>"
|
367
|
-
return "Compact" if type == "<Balance as HasCompact>::Type"
|
368
|
-
return "Compact" if type == "<BlockNumber as HasCompact>::Type"
|
369
|
-
return "Compact" if type == "Compact<Balance>"
|
370
|
-
return "Compact" if type == "Compact<BlockNumber>"
|
371
|
-
return "CompactMoment" if type == "<Moment as HasCompact>::Type"
|
372
|
-
return "CompactMoment" if type == "Compact<Moment>"
|
373
|
-
return "InherentOfflineReport" if type == "<InherentOfflineReport as InherentOfflineReport>::Inherent"
|
374
|
-
return "AccountData" if type == "AccountData<Balance>"
|
375
|
-
|
376
|
-
if type =~ /\[U\d+; \d+\]/
|
377
|
-
byte_length = type.scan(/\[U\d+; (\d+)\]/).first.first.to_i
|
378
|
-
return "VecU8Length#{byte_length}"
|
379
|
-
end
|
380
|
-
|
381
|
-
type
|
382
62
|
end
|
383
63
|
|
384
64
|
def green(text)
|
@@ -389,6 +69,24 @@ def yellow(text)
|
|
389
69
|
"\033[33m#{text}\033[0m"
|
390
70
|
end
|
391
71
|
|
72
|
+
class String
|
73
|
+
def upcase_first
|
74
|
+
self.sub(/\S/, &:upcase)
|
75
|
+
end
|
76
|
+
|
77
|
+
def camelize2
|
78
|
+
self.split('_').collect(&:upcase_first).join
|
79
|
+
end
|
80
|
+
|
81
|
+
def underscore2
|
82
|
+
self.gsub(/::/, '/').
|
83
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
84
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
85
|
+
tr("-", "_").
|
86
|
+
downcase
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
392
90
|
# https://www.ruby-forum.com/t/question-about-hex-signed-int/125510/4
|
393
91
|
# machine bit length:
|
394
92
|
# machine_byte_length = ['foo'].pack('p').size
|
@@ -426,3 +124,6 @@ class ::Hash
|
|
426
124
|
Hash[h]
|
427
125
|
end
|
428
126
|
end
|
127
|
+
|
128
|
+
Scale::Types.debug = false
|
129
|
+
Scale::Types.logger = Logger.new(STDOUT)
|
data/lib/scale/base.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Scale
|
2
2
|
module Types
|
3
3
|
|
4
|
-
module
|
4
|
+
module Base
|
5
5
|
attr_reader :value
|
6
6
|
|
7
7
|
def initialize(value)
|
@@ -9,62 +9,74 @@ module Scale
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def ==(other)
|
12
|
-
value == other.value
|
12
|
+
self.class == other.class && self.value == other.value
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_human
|
16
16
|
if @value.class == ::Hash
|
17
17
|
@value.transform_values do |v|
|
18
|
-
if v.class.included_modules.include?(
|
18
|
+
if v.class.included_modules.include?(Base)
|
19
19
|
v.to_human
|
20
20
|
else
|
21
21
|
v
|
22
22
|
end
|
23
|
-
end
|
23
|
+
end.transform_keys(&:to_sym)
|
24
24
|
elsif @value.class == ::Array
|
25
25
|
@value.map do |v|
|
26
|
-
if v.class.included_modules.include?(
|
26
|
+
if v.class.included_modules.include?(Base)
|
27
27
|
v.to_human
|
28
28
|
else
|
29
29
|
v
|
30
30
|
end
|
31
31
|
end
|
32
|
+
elsif @value.class.include?(Base)
|
33
|
+
@value.to_human
|
32
34
|
else
|
33
35
|
@value
|
34
36
|
end
|
35
37
|
end
|
38
|
+
|
39
|
+
module ClassMethods
|
40
|
+
def inherited(child)
|
41
|
+
child.const_set(:TYPE_NAME, child.name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.included(base)
|
46
|
+
base.extend(ClassMethods)
|
47
|
+
base.const_set(:TYPE_NAME, base.name)
|
48
|
+
end
|
36
49
|
end
|
37
50
|
|
38
|
-
# value
|
51
|
+
# if value is bool, see type `OptionBool` in types.rb
|
39
52
|
module Option
|
40
|
-
include
|
53
|
+
include Base
|
41
54
|
|
42
55
|
module ClassMethods
|
43
56
|
def decode(scale_bytes)
|
57
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
44
58
|
byte = scale_bytes.get_next_bytes(1)
|
45
59
|
if byte == [0]
|
60
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
46
61
|
new(nil)
|
47
62
|
elsif byte == [1]
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
else
|
59
|
-
raise "bad data"
|
60
|
-
end
|
63
|
+
# big process
|
64
|
+
type =
|
65
|
+
if self::INNER_TYPE.class == ::String
|
66
|
+
Scale::Types.get(self::INNER_TYPE)
|
67
|
+
else
|
68
|
+
self::INNER_TYPE
|
69
|
+
end
|
70
|
+
value = type.decode(scale_bytes)
|
71
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
72
|
+
new(value)
|
61
73
|
else
|
62
|
-
raise "
|
74
|
+
raise BadDataError.new("Bad scale data for #{self::TYPE_NAME}")
|
63
75
|
end
|
64
76
|
end
|
65
77
|
|
66
|
-
def inner_type(
|
67
|
-
const_set(:
|
78
|
+
def inner_type(type)
|
79
|
+
const_set(:INNER_TYPE, type)
|
68
80
|
end
|
69
81
|
end
|
70
82
|
|
@@ -77,21 +89,21 @@ module Scale
|
|
77
89
|
if value.nil?
|
78
90
|
"00"
|
79
91
|
else
|
80
|
-
return "02" if value.class == TrueClass && value === true
|
81
|
-
return "01" if value.class == FalseClass && value === false
|
82
92
|
"01" + value.encode
|
83
93
|
end
|
84
94
|
end
|
85
95
|
end
|
86
96
|
|
87
97
|
module FixedWidthInt
|
88
|
-
include
|
98
|
+
include Base
|
89
99
|
|
90
100
|
module ClassMethods
|
91
101
|
def decode(scale_bytes)
|
102
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
92
103
|
bytes = scale_bytes.get_next_bytes self::BYTE_LENGTH
|
93
104
|
bit_length = bytes.length.to_i * 8
|
94
105
|
value = bytes.reverse.bytes_to_hex.to_i(16).to_signed(bit_length)
|
106
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
95
107
|
new(value)
|
96
108
|
end
|
97
109
|
end
|
@@ -111,16 +123,21 @@ module Scale
|
|
111
123
|
end
|
112
124
|
|
113
125
|
module FixedWidthUInt
|
114
|
-
include
|
126
|
+
include Base
|
115
127
|
|
116
128
|
module ClassMethods
|
117
129
|
attr_accessor :byte_length
|
118
130
|
|
119
131
|
def decode(scale_bytes)
|
132
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
120
133
|
bytes = scale_bytes.get_next_bytes self::BYTE_LENGTH
|
121
134
|
bytes_reversed = bytes.reverse
|
122
135
|
hex = bytes_reversed.reduce("0x") { |hex, byte| hex + byte.to_s(16).rjust(2, "0") }
|
123
|
-
new(hex.to_i(16))
|
136
|
+
result = new(hex.to_i(16))
|
137
|
+
|
138
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
139
|
+
|
140
|
+
result
|
124
141
|
end
|
125
142
|
end
|
126
143
|
|
@@ -139,68 +156,85 @@ module Scale
|
|
139
156
|
end
|
140
157
|
|
141
158
|
module Struct
|
142
|
-
include
|
159
|
+
include Base
|
143
160
|
# new(1.to_u32, U32(69))
|
144
161
|
module ClassMethods
|
162
|
+
def inherited(child)
|
163
|
+
child.const_set(:TYPE_NAME, child.name)
|
164
|
+
end
|
165
|
+
|
145
166
|
def decode(scale_bytes)
|
146
|
-
|
147
|
-
|
148
|
-
|
167
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
168
|
+
|
169
|
+
# item_values:
|
170
|
+
# {
|
171
|
+
# a: ...,
|
172
|
+
# b: ...
|
173
|
+
# }
|
174
|
+
item_values = {}
|
175
|
+
self::ITEMS.each_pair do |item_name, item_type|
|
176
|
+
if item_type.class == ::String
|
177
|
+
item_type = Scale::Types.get(item_type)
|
178
|
+
end
|
179
|
+
item_values[item_name] = item_type.decode(scale_bytes)
|
149
180
|
end
|
150
181
|
|
151
|
-
value = {}
|
152
|
-
self::ITEM_NAMES.zip(item_values) do |attr, val|
|
153
|
-
|
154
|
-
end
|
182
|
+
# value = {}
|
183
|
+
# self::ITEM_NAMES.zip(item_values) do |attr, val|
|
184
|
+
# value[attr] = val
|
185
|
+
# end
|
155
186
|
|
156
|
-
|
157
|
-
|
158
|
-
|
187
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
188
|
+
|
189
|
+
result = new(item_values)
|
190
|
+
item_values.each_pair do |item_name, item_value|
|
191
|
+
result.send "#{item_name.to_s}=", item_value
|
159
192
|
end
|
193
|
+
|
160
194
|
result
|
161
195
|
end
|
162
196
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
attr_names << attr_name.to_s.gsub("-", "")
|
169
|
-
attr_type_strs << attr_type_str
|
170
|
-
end
|
171
|
-
|
172
|
-
const_set(:ITEM_NAMES, attr_names)
|
173
|
-
const_set(:ITEM_TYPE_STRS, attr_type_strs)
|
174
|
-
attr_accessor *attr_names
|
197
|
+
# items(a: Scale::Types::Type1, b: "Type2")
|
198
|
+
def items(**items)
|
199
|
+
const_set(:ITEMS, items)
|
200
|
+
item_names = items.keys
|
201
|
+
attr_accessor *item_names
|
175
202
|
end
|
176
203
|
end
|
177
204
|
|
178
205
|
def self.included(base)
|
179
206
|
base.extend ClassMethods
|
207
|
+
base.const_set(:TYPE_NAME, base.name)
|
180
208
|
end
|
181
209
|
|
182
210
|
def encode
|
183
|
-
|
184
|
-
|
185
|
-
result << attr_value.encode
|
186
|
-
end
|
211
|
+
value.values.map do |item_value|
|
212
|
+
item_value.encode
|
187
213
|
end.join
|
188
214
|
end
|
189
215
|
end
|
190
216
|
|
191
217
|
module Tuple
|
192
|
-
include
|
218
|
+
include Base
|
193
219
|
|
194
220
|
module ClassMethods
|
195
221
|
def decode(scale_bytes)
|
196
|
-
|
197
|
-
|
222
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
223
|
+
|
224
|
+
values = self::INNER_TYPES.map do |type|
|
225
|
+
if type.class == ::String
|
226
|
+
type = Scale::Types.get(type)
|
227
|
+
end
|
228
|
+
type.decode(scale_bytes)
|
198
229
|
end
|
230
|
+
|
231
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
199
232
|
new(values)
|
200
233
|
end
|
201
234
|
|
202
|
-
|
203
|
-
|
235
|
+
# inner_types Scale::Types::U8, "U8"
|
236
|
+
def inner_types(*inner_types)
|
237
|
+
const_set(:INNER_TYPES, inner_types)
|
204
238
|
end
|
205
239
|
end
|
206
240
|
|
@@ -214,38 +248,46 @@ module Scale
|
|
214
248
|
end
|
215
249
|
|
216
250
|
module Enum
|
217
|
-
include
|
251
|
+
include Base
|
252
|
+
|
253
|
+
attr_accessor :index
|
218
254
|
|
219
255
|
module ClassMethods
|
220
256
|
def decode(scale_bytes)
|
257
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
221
258
|
index = scale_bytes.get_next_bytes(1)[0]
|
222
|
-
if const_defined? "
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
259
|
+
if const_defined? "ITEMS"
|
260
|
+
type = self::ITEMS.values[index]
|
261
|
+
if type.class == ::String
|
262
|
+
type = Scale::Types.get(type)
|
263
|
+
end
|
264
|
+
value = type.decode(scale_bytes)
|
265
|
+
elsif const_defined? "INNER_TYPES"
|
266
|
+
type = self::INNER_TYPES[index]
|
267
|
+
if type.class == ::String
|
268
|
+
type = Scale::Types.get(type)
|
269
|
+
end
|
270
|
+
value = type.decode(scale_bytes)
|
271
|
+
else # VALUES
|
227
272
|
value = self::VALUES[index]
|
228
273
|
end
|
229
|
-
|
274
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
275
|
+
result = new(value)
|
276
|
+
result.index = index
|
277
|
+
result
|
230
278
|
end
|
231
279
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
items.each_pair do |attr_name, attr_type_str|
|
238
|
-
attr_names << attr_name
|
239
|
-
attr_type_strs << attr_type_str
|
240
|
-
end
|
280
|
+
# inner_types(Scale::Types::Compact, "Hex")
|
281
|
+
def inner_types(*inner_types)
|
282
|
+
const_set(:INNER_TYPES, inner_types)
|
283
|
+
end
|
241
284
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
const_set(:ITEM_TYPE_STRS, items)
|
246
|
-
end
|
285
|
+
# items(Item1: Scale::Types::Compact, Item2: "Hex")
|
286
|
+
def items(**items)
|
287
|
+
const_set(:ITEMS, items)
|
247
288
|
end
|
248
289
|
|
290
|
+
# [1, "hello"]
|
249
291
|
def values(*values)
|
250
292
|
const_set(:VALUES, values)
|
251
293
|
end
|
@@ -256,17 +298,17 @@ module Scale
|
|
256
298
|
end
|
257
299
|
|
258
300
|
def encode
|
259
|
-
if self.class.const_defined? "
|
260
|
-
|
261
|
-
index = self.class::ITEM_TYPE_STRS.index(value_type_str).to_s(16).rjust(2, "0")
|
262
|
-
index + value.encode
|
301
|
+
if self.class.const_defined? "ITEMS"
|
302
|
+
index.to_s(16).rjust(2, "0") + value.encode
|
263
303
|
else
|
264
304
|
self.class::VALUES.index(value).to_s(16).rjust(2, "0")
|
265
305
|
end
|
266
306
|
end
|
267
307
|
|
268
308
|
def to_human
|
269
|
-
if self.class.const_defined? "
|
309
|
+
if self.class.const_defined? "ITEMS"
|
310
|
+
@value.to_human
|
311
|
+
elsif self.class.const_defined? "INNER_TYPES"
|
270
312
|
@value.to_human
|
271
313
|
else
|
272
314
|
@value
|
@@ -275,22 +317,23 @@ module Scale
|
|
275
317
|
end
|
276
318
|
|
277
319
|
module Vec
|
278
|
-
include
|
320
|
+
include Base # value is an array
|
279
321
|
|
280
322
|
module ClassMethods
|
281
323
|
def decode(scale_bytes, raw = false)
|
324
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
282
325
|
number = Scale::Types::Compact.decode(scale_bytes).value
|
283
326
|
items = []
|
284
327
|
number.times do
|
285
|
-
|
286
|
-
item = type.decode(scale_bytes)
|
328
|
+
item = self::INNER_TYPE.decode(scale_bytes)
|
287
329
|
items << item
|
288
330
|
end
|
331
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
289
332
|
raw ? items : new(items)
|
290
333
|
end
|
291
334
|
|
292
|
-
def inner_type(
|
293
|
-
const_set(:
|
335
|
+
def inner_type(type)
|
336
|
+
const_set(:INNER_TYPE, type)
|
294
337
|
end
|
295
338
|
end
|
296
339
|
|
@@ -309,14 +352,16 @@ module Scale
|
|
309
352
|
end
|
310
353
|
|
311
354
|
module Set
|
312
|
-
include
|
355
|
+
include Base
|
313
356
|
|
314
357
|
module ClassMethods
|
315
358
|
def decode(scale_bytes)
|
359
|
+
puts " BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
316
360
|
value = "Scale::Types::U#{self::BYTE_LENGTH * 8}".constantize2.decode(scale_bytes).value
|
317
361
|
return new [] unless value || value <= 0
|
318
362
|
|
319
363
|
result = self::ITEMS.select { |_, mask| value & mask > 0 }.keys
|
364
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
320
365
|
new result
|
321
366
|
end
|
322
367
|
|
@@ -345,18 +390,21 @@ module Scale
|
|
345
390
|
end
|
346
391
|
|
347
392
|
module VecU8FixedLength
|
348
|
-
include
|
393
|
+
include Base
|
349
394
|
|
350
395
|
module ClassMethods
|
351
396
|
def decode(scale_bytes)
|
397
|
+
puts " BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
352
398
|
byte_length = self::BYTE_LENGTH
|
353
399
|
raise "#{self.name} byte length is wrong: #{byte_length}" unless %w[2 3 4 8 16 20 32 64 128 256].include?(byte_length.to_s)
|
354
400
|
|
355
401
|
bytes = scale_bytes.get_next_bytes(byte_length)
|
356
402
|
str = bytes.pack("C*").force_encoding("utf-8")
|
357
403
|
if str.valid_encoding?
|
404
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
358
405
|
new str
|
359
406
|
else
|
407
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
360
408
|
new bytes.bytes_to_hex
|
361
409
|
end
|
362
410
|
end
|
@@ -379,5 +427,39 @@ module Scale
|
|
379
427
|
end
|
380
428
|
end
|
381
429
|
|
430
|
+
module Array
|
431
|
+
include Base
|
432
|
+
|
433
|
+
module ClassMethods
|
434
|
+
def decode(scale_bytes)
|
435
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
436
|
+
items = (0 ... self::LENGTH).map do |_|
|
437
|
+
self::INNER_TYPE.decode(scale_bytes)
|
438
|
+
end
|
439
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
440
|
+
new(items)
|
441
|
+
end
|
442
|
+
|
443
|
+
def inner_type(type)
|
444
|
+
const_set(:INNER_TYPE, type)
|
445
|
+
end
|
446
|
+
|
447
|
+
def length(len)
|
448
|
+
const_set(:LENGTH, len)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def self.included(base)
|
453
|
+
base.extend ClassMethods
|
454
|
+
end
|
455
|
+
|
456
|
+
def encode
|
457
|
+
self.value.map do |item|
|
458
|
+
item.encode
|
459
|
+
end.join
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
|
382
464
|
end
|
383
465
|
end
|