scale.rb 0.2.14 → 0.2.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Cargo.lock +2007 -11
- data/Cargo.toml +9 -2
- data/Dockerfile +4 -1
- data/Gemfile.lock +45 -46
- data/README.md +28 -1
- data/exe/scale +39 -70
- data/lib/address.rb +3 -0
- data/lib/common.rb +163 -0
- data/lib/helper.rb +128 -0
- data/lib/metadata/metadata.rb +15 -1
- data/lib/scale.rb +105 -33
- data/lib/scale/base.rb +52 -13
- data/lib/scale/block.rb +17 -27
- data/lib/scale/types.rb +71 -4
- data/lib/scale/version.rb +1 -1
- data/lib/substrate_client.rb +170 -0
- data/lib/type_registry/{crab-28.json → crab.json} +474 -126
- data/lib/type_registry/darwinia.json +701 -136
- data/lib/type_registry/default.json +2 -2
- data/lib/type_registry/pangolin.json +332 -0
- data/scale.gemspec +7 -5
- data/scripts/block_events.rb +2 -3
- data/src/lib.rs +42 -1
- data/src/storage_key.rs +41 -0
- metadata +52 -26
- data/.DS_Store +0 -0
- data/lib/type_registry/darwinia-8.json +0 -662
- 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/lib/helper.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
|
2
|
+
class SubstrateClient::Helper
|
3
|
+
class << self
|
4
|
+
def generate_storage_key_from_metadata(metadata, module_name, storage_name, params = nil)
|
5
|
+
# find the storage item from metadata
|
6
|
+
metadata_modules = metadata.value.value[:metadata][:modules]
|
7
|
+
metadata_module = metadata_modules.detect { |mm| mm[:name] == module_name }
|
8
|
+
raise "Module '#{module_name}' not exist" unless metadata_module
|
9
|
+
storage_item = metadata_module[:storage][:items].detect { |item| item[:name] == storage_name }
|
10
|
+
raise "Storage item '#{storage_name}' not exist. \n#{metadata_module.inspect}" unless storage_item
|
11
|
+
|
12
|
+
if storage_item[:type][:Plain]
|
13
|
+
return_type = storage_item[:type][:Plain]
|
14
|
+
elsif map = storage_item[:type][:Map]
|
15
|
+
raise "Storage call of type \"Map\" requires 1 parameter" if params.nil? || params.length != 1
|
16
|
+
|
17
|
+
hasher = map[:hasher]
|
18
|
+
return_type = map[:value]
|
19
|
+
# TODO: decode to account id if param is address
|
20
|
+
# params[0] = decode(params[0]) if map[:key] == "AccountId"
|
21
|
+
type = Scale::Types.get(map[:key])
|
22
|
+
params[0] = type.new(params[0]).encode
|
23
|
+
elsif map = storage_item[:type][:DoubleMap]
|
24
|
+
raise "Storage call of type \"DoubleMapType\" requires 2 parameters" if params.nil? || params.length != 2
|
25
|
+
|
26
|
+
hasher = map[:hasher]
|
27
|
+
hasher2 = map[:key2Hasher]
|
28
|
+
return_type = map[:value]
|
29
|
+
params[0] = Scale::Types.get(map[:key1]).new(params[0]).encode
|
30
|
+
params[1] = Scale::Types.get(map[:key2]).new(params[1]).encode
|
31
|
+
else
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
storage_prefix = metadata_module[:storage][:prefix]
|
36
|
+
storage_key = generate_storage_key(
|
37
|
+
storage_prefix.nil? ? module_name : storage_prefix,
|
38
|
+
storage_name,
|
39
|
+
params,
|
40
|
+
hasher,
|
41
|
+
hasher2,
|
42
|
+
metadata.value.value[:metadata][:version]
|
43
|
+
)
|
44
|
+
[storage_key, return_type]
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_storage_key(module_name, storage_name, params = nil, hasher = nil, hasher2 = nil, metadata_version = nil)
|
48
|
+
metadata_version = 12 if metadata_version.nil?
|
49
|
+
if metadata_version and metadata_version >= 9
|
50
|
+
storage_key = Crypto.twox128(module_name) + Crypto.twox128(storage_name)
|
51
|
+
|
52
|
+
params&.each_with_index do |param, index|
|
53
|
+
if index == 0
|
54
|
+
param_hasher = hasher
|
55
|
+
elsif index == 1
|
56
|
+
param_hasher = hasher2
|
57
|
+
else
|
58
|
+
raise "Unexpected third parameter for storage call"
|
59
|
+
end
|
60
|
+
|
61
|
+
param_key = if param.class == String && param.start_with?("0x")
|
62
|
+
param.hex_to_bytes
|
63
|
+
else
|
64
|
+
param.encode().hex_to_bytes
|
65
|
+
end
|
66
|
+
param_hasher = "Twox128" if param_hasher.nil?
|
67
|
+
storage_key += Crypto.send(param_hasher.underscore2, param_key)
|
68
|
+
end
|
69
|
+
|
70
|
+
"0x#{storage_key}"
|
71
|
+
else
|
72
|
+
# TODO: add test
|
73
|
+
storage_key = module_name + " " + storage_name
|
74
|
+
|
75
|
+
unless params.nil?
|
76
|
+
params = [params] if params.class != ::Array
|
77
|
+
params_key = params.join("")
|
78
|
+
hasher = "Twox128" if hasher.nil?
|
79
|
+
storage_key += params_key.hex_to_bytes.bytes_to_utf8
|
80
|
+
end
|
81
|
+
|
82
|
+
"0x#{Crypto.send( hasher.underscore2, storage_key )}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def compose_call_from_metadata(metadata, module_name, call_name, params)
|
87
|
+
call = metadata.get_module_call(module_name, call_name)
|
88
|
+
|
89
|
+
value = {
|
90
|
+
call_index: call[:lookup],
|
91
|
+
module_name: module_name,
|
92
|
+
call_name: call_name,
|
93
|
+
params: []
|
94
|
+
}
|
95
|
+
|
96
|
+
params.keys.each_with_index do |call_param_name, i|
|
97
|
+
param_value = params[call_param_name]
|
98
|
+
value[:params] << {
|
99
|
+
name: call_param_name.to_s,
|
100
|
+
type: call[:args][i][:type],
|
101
|
+
value: param_value
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
Scale::Types::Extrinsic.new(value).encode
|
106
|
+
end
|
107
|
+
|
108
|
+
def decode_block(block)
|
109
|
+
block["block"]["header"]["number"] = block["block"]["header"]["number"].to_i(16)
|
110
|
+
|
111
|
+
block["block"]["extrinsics_decoded"] = []
|
112
|
+
block["block"]["extrinsics"].each_with_index do |hex, i|
|
113
|
+
scale_bytes = Scale::Bytes.new(hex)
|
114
|
+
block["block"]["extrinsics_decoded"][i] = Scale::Types::Extrinsic.decode(scale_bytes).to_human
|
115
|
+
end
|
116
|
+
|
117
|
+
block['block']['header']["digest"]["logs_decoded"] = []
|
118
|
+
block['block']['header']["digest"]["logs"].each_with_index do |hex, i|
|
119
|
+
scale_bytes = Scale::Bytes.new(hex)
|
120
|
+
log = Scale::Types::LogDigest.decode(scale_bytes).to_human
|
121
|
+
block['block']['header']["digest"]["logs_decoded"][i] = log
|
122
|
+
end
|
123
|
+
|
124
|
+
block
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
data/lib/metadata/metadata.rb
CHANGED
@@ -7,7 +7,7 @@ module Scale
|
|
7
7
|
bytes = scale_bytes.get_next_bytes(4)
|
8
8
|
if bytes.bytes_to_utf8 == "meta"
|
9
9
|
metadata_version = Scale::Types.type_of("Enum", %w[MetadataV0 MetadataV1 MetadataV2 MetadataV3 MetadataV4 MetadataV5 MetadataV6 MetadataV7 MetadataV8 MetadataV9 MetadataV10 MetadataV11 MetadataV12]).decode(scale_bytes).value
|
10
|
-
metadata = Metadata.new "Scale::Types::#{metadata_version}".
|
10
|
+
metadata = Metadata.new "Scale::Types::#{metadata_version}".constantize2.decode(scale_bytes)
|
11
11
|
metadata.version = metadata_version[9..].to_i
|
12
12
|
else
|
13
13
|
scale_bytes.reset_offset
|
@@ -35,6 +35,16 @@ module Scale
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
def get_module_storage(module_name, storage_name)
|
40
|
+
the_module = get_module(module_name)
|
41
|
+
if the_module[:storage].class == Array
|
42
|
+
storages = the_module[:storage]
|
43
|
+
else
|
44
|
+
storages = the_module[:storage][:items]
|
45
|
+
end
|
46
|
+
storages.find {|storage| storage[:name] == storage_name}
|
47
|
+
end
|
38
48
|
end
|
39
49
|
|
40
50
|
class MetadataModule
|
@@ -68,6 +78,10 @@ module Scale
|
|
68
78
|
|
69
79
|
MetadataModule.new(result)
|
70
80
|
end
|
81
|
+
|
82
|
+
def get_storage(storage_name)
|
83
|
+
self.value[:storage].find { |storage| storage[:name].downcase == storage_name.downcase }
|
84
|
+
end
|
71
85
|
end
|
72
86
|
|
73
87
|
class MetadataModuleStorage
|
data/lib/scale.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require "scale/version"
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "common"
|
4
|
+
|
4
5
|
require "json"
|
5
|
-
require "active_support"
|
6
|
-
require "active_support/core_ext/string"
|
7
6
|
require "singleton"
|
8
7
|
|
9
8
|
require "scale/base"
|
@@ -26,13 +25,40 @@ require "metadata/metadata_v10"
|
|
26
25
|
require "metadata/metadata_v11"
|
27
26
|
require "metadata/metadata_v12"
|
28
27
|
|
28
|
+
require "substrate_client"
|
29
|
+
require "logger"
|
30
|
+
require "helper"
|
31
|
+
|
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
|
+
|
29
50
|
module Scale
|
30
51
|
class Error < StandardError; end
|
31
52
|
|
32
53
|
class TypeRegistry
|
33
54
|
include Singleton
|
34
|
-
|
35
|
-
|
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
|
36
62
|
attr_accessor :metadata
|
37
63
|
|
38
64
|
def load(spec_name: nil, custom_types: nil)
|
@@ -43,13 +69,18 @@ module Scale
|
|
43
69
|
|
44
70
|
default_types, _, _ = load_chain_spec_types("default")
|
45
71
|
|
46
|
-
if spec_name
|
72
|
+
if spec_name
|
73
|
+
begin
|
74
|
+
@spec_name = spec_name
|
75
|
+
spec_types, @versioning, @spec_version = load_chain_spec_types(spec_name)
|
76
|
+
@types = default_types.merge(spec_types)
|
77
|
+
rescue => ex
|
78
|
+
puts "There is no types json file named #{spec_name}"
|
79
|
+
@types = default_types
|
80
|
+
end
|
81
|
+
else
|
47
82
|
@spec_name = "default"
|
48
83
|
@types = default_types
|
49
|
-
else
|
50
|
-
@spec_name = spec_name
|
51
|
-
spec_types, @versioning, @spec_version = load_chain_spec_types(spec_name)
|
52
|
-
@types = default_types.merge(spec_types)
|
53
84
|
end
|
54
85
|
|
55
86
|
self.custom_types = custom_types
|
@@ -63,7 +94,8 @@ module Scale
|
|
63
94
|
|
64
95
|
if @spec_version && @versioning
|
65
96
|
@versioning.each do |item|
|
66
|
-
if @spec_version >= item["runtime_range"][0] &&
|
97
|
+
if @spec_version >= item["runtime_range"][0] &&
|
98
|
+
( item["runtime_range"][1].nil? || @spec_version <= item["runtime_range"][1] )
|
67
99
|
all_types.merge!(item["types"])
|
68
100
|
end
|
69
101
|
end
|
@@ -176,7 +208,7 @@ module Scale
|
|
176
208
|
types.each do |name, body|
|
177
209
|
if body.class == String
|
178
210
|
target_type = "Scale::Types::#{body}"
|
179
|
-
klass = Class.new(target_type.
|
211
|
+
klass = Class.new(target_type.constantize2) do
|
180
212
|
end
|
181
213
|
elsif body.class == Hash
|
182
214
|
if body["type"] == "struct"
|
@@ -210,12 +242,18 @@ module Scale
|
|
210
242
|
end
|
211
243
|
|
212
244
|
module Types
|
245
|
+
class << self
|
246
|
+
attr_accessor :debug
|
247
|
+
end
|
248
|
+
|
213
249
|
def self.list
|
214
250
|
TypeRegistry.instance.types
|
215
251
|
end
|
216
252
|
|
217
253
|
def self.get(type_name)
|
218
|
-
TypeRegistry.instance.get(type_name)
|
254
|
+
type = TypeRegistry.instance.get(type_name)
|
255
|
+
raise "Type '#{type_name}' not exist" if type.nil?
|
256
|
+
type
|
219
257
|
end
|
220
258
|
|
221
259
|
def self.constantize(type)
|
@@ -240,13 +278,32 @@ module Scale
|
|
240
278
|
type_str = type_strs.first
|
241
279
|
inner_type_str = type_strs.last
|
242
280
|
|
243
|
-
if type_str == "Vec"
|
244
|
-
|
245
|
-
|
246
|
-
|
281
|
+
if type_str == "Vec"
|
282
|
+
name = "#{type_str}<#{inner_type_str.camelize2}>"
|
283
|
+
name = fix(name)
|
284
|
+
|
285
|
+
if !Scale::Types.const_defined?(name)
|
286
|
+
klass = Class.new do
|
287
|
+
include Scale::Types::Vec
|
288
|
+
inner_type inner_type_str
|
289
|
+
end
|
290
|
+
Scale::Types.const_set name, klass
|
291
|
+
else
|
292
|
+
Scale::Types.const_get name
|
293
|
+
end
|
294
|
+
elsif type_str == "Option"
|
295
|
+
name = "#{type_str}<#{inner_type_str.camelize2}>"
|
296
|
+
name = fix(name)
|
297
|
+
|
298
|
+
if !Scale::Types.const_defined?(name)
|
299
|
+
klass = Class.new do
|
300
|
+
include Scale::Types::Option
|
301
|
+
inner_type inner_type_str
|
302
|
+
end
|
303
|
+
Scale::Types.const_set name, klass
|
304
|
+
else
|
305
|
+
Scale::Types.const_get name
|
247
306
|
end
|
248
|
-
name = "#{type_str}_Of_#{inner_type_str.camelize}_#{klass.object_id}"
|
249
|
-
Scale::Types.const_set fix(name), klass
|
250
307
|
else
|
251
308
|
raise "#{type_str} not support inner type: #{type_string}"
|
252
309
|
end
|
@@ -263,12 +320,17 @@ module Scale
|
|
263
320
|
type_str.strip.tr(";", ",")
|
264
321
|
end
|
265
322
|
|
266
|
-
|
267
|
-
|
268
|
-
|
323
|
+
name = "TupleOf#{type_strs.map(&:camelize2).join("")}"
|
324
|
+
name = fix(name)
|
325
|
+
if !Scale::Types.const_defined?(name)
|
326
|
+
klass = Class.new do
|
327
|
+
include Scale::Types::Tuple
|
328
|
+
inner_types *type_strs
|
329
|
+
end
|
330
|
+
Scale::Types.const_set name, klass
|
331
|
+
else
|
332
|
+
Scale::Types.const_get name
|
269
333
|
end
|
270
|
-
name = "Tuple_Of_#{type_strs.map(&:camelize).join("_")}_#{klass.object_id}"
|
271
|
-
Scale::Types.const_set fix(name), klass
|
272
334
|
else
|
273
335
|
if type_string == "Enum"
|
274
336
|
# TODO: combine values to items
|
@@ -280,7 +342,7 @@ module Scale
|
|
280
342
|
values(*values)
|
281
343
|
end
|
282
344
|
end
|
283
|
-
name = values.class == ::Hash ? values.values.map(&:
|
345
|
+
name = values.class == ::Hash ? values.values.map(&:camelize2).join("_") : values.map(&:camelize2).join("_")
|
284
346
|
name = "Enum_Of_#{name}_#{klass.object_id}"
|
285
347
|
Scale::Types.const_set fix(name), klass
|
286
348
|
elsif type_string == "Struct"
|
@@ -288,19 +350,19 @@ module Scale
|
|
288
350
|
include Scale::Types::Struct
|
289
351
|
items values
|
290
352
|
end
|
291
|
-
name = "Struct_Of_#{values.values.map(&:
|
353
|
+
name = "Struct_Of_#{values.values.map(&:camelize2).join("_")}_#{klass.object_id}"
|
292
354
|
Scale::Types.const_set fix(name), klass
|
293
355
|
elsif type_string == "Set"
|
294
356
|
klass = Class.new do
|
295
357
|
include Scale::Types::Set
|
296
358
|
items values, 1
|
297
359
|
end
|
298
|
-
name = "Set_Of_#{values.keys.map(&:
|
360
|
+
name = "Set_Of_#{values.keys.map(&:camelize2).join("_")}_#{klass.object_id}"
|
299
361
|
Scale::Types.const_set fix(name), klass
|
300
362
|
else
|
301
363
|
type_name = (type_string.start_with?("Scale::Types::") ? type_string : "Scale::Types::#{type_string}")
|
302
364
|
begin
|
303
|
-
type_name.
|
365
|
+
type_name.constantize2
|
304
366
|
rescue NameError => e
|
305
367
|
puts "#{type_string} is not defined"
|
306
368
|
end
|
@@ -311,12 +373,20 @@ module Scale
|
|
311
373
|
|
312
374
|
end
|
313
375
|
|
376
|
+
# def fix(name)
|
377
|
+
# name
|
378
|
+
# .gsub("<", "˂").gsub(">", "˃")
|
379
|
+
# .gsub("(", "⁽").gsub(")", "⁾")
|
380
|
+
# .gsub(" ", "").gsub(",", "‚")
|
381
|
+
# .gsub(":", "։")
|
382
|
+
# end
|
383
|
+
|
314
384
|
def fix(name)
|
315
385
|
name
|
316
|
-
.gsub("<", "
|
317
|
-
.gsub("(", "
|
318
|
-
.gsub(" ", "").gsub(",", "
|
319
|
-
.gsub(":", "
|
386
|
+
.gsub("<", "").gsub(">", "")
|
387
|
+
.gsub("(", "").gsub(")", "")
|
388
|
+
.gsub(" ", "").gsub(",", "")
|
389
|
+
.gsub(":", "")
|
320
390
|
end
|
321
391
|
|
322
392
|
def rename(type)
|
@@ -342,7 +412,7 @@ def rename(type)
|
|
342
412
|
return "AccountData" if type == "AccountData<Balance>"
|
343
413
|
|
344
414
|
if type =~ /\[U\d+; \d+\]/
|
345
|
-
byte_length = type.scan(/\[U\d+; (\d+)\]/).first.first
|
415
|
+
byte_length = type.scan(/\[U\d+; (\d+)\]/).first.first.to_i
|
346
416
|
return "VecU8Length#{byte_length}"
|
347
417
|
end
|
348
418
|
|
@@ -394,3 +464,5 @@ class ::Hash
|
|
394
464
|
Hash[h]
|
395
465
|
end
|
396
466
|
end
|
467
|
+
|
468
|
+
Scale::Types.debug = false
|
data/lib/scale/base.rb
CHANGED
@@ -33,6 +33,17 @@ module Scale
|
|
33
33
|
@value
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def inherited(child)
|
39
|
+
child.const_set(:TYPE_NAME, child.name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.included(base)
|
44
|
+
base.extend(ClassMethods)
|
45
|
+
base.const_set(:TYPE_NAME, base.name)
|
46
|
+
end
|
36
47
|
end
|
37
48
|
|
38
49
|
# value: one of nil, false, true, scale object
|
@@ -41,19 +52,24 @@ module Scale
|
|
41
52
|
|
42
53
|
module ClassMethods
|
43
54
|
def decode(scale_bytes)
|
55
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
44
56
|
byte = scale_bytes.get_next_bytes(1)
|
45
57
|
if byte == [0]
|
58
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
46
59
|
new(nil)
|
47
60
|
elsif byte == [1]
|
48
61
|
if self::INNER_TYPE_STR == "boolean"
|
62
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
49
63
|
new(false)
|
50
64
|
else
|
51
65
|
# big process
|
52
66
|
value = Scale::Types.get(self::INNER_TYPE_STR).decode(scale_bytes)
|
67
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
53
68
|
new(value)
|
54
69
|
end
|
55
70
|
elsif byte == [2]
|
56
71
|
if self::INNER_TYPE_STR == "boolean"
|
72
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
57
73
|
new(true)
|
58
74
|
else
|
59
75
|
raise "bad data"
|
@@ -89,9 +105,11 @@ module Scale
|
|
89
105
|
|
90
106
|
module ClassMethods
|
91
107
|
def decode(scale_bytes)
|
108
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
92
109
|
bytes = scale_bytes.get_next_bytes self::BYTE_LENGTH
|
93
110
|
bit_length = bytes.length.to_i * 8
|
94
111
|
value = bytes.reverse.bytes_to_hex.to_i(16).to_signed(bit_length)
|
112
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
95
113
|
new(value)
|
96
114
|
end
|
97
115
|
end
|
@@ -117,10 +135,15 @@ module Scale
|
|
117
135
|
attr_accessor :byte_length
|
118
136
|
|
119
137
|
def decode(scale_bytes)
|
138
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
120
139
|
bytes = scale_bytes.get_next_bytes self::BYTE_LENGTH
|
121
140
|
bytes_reversed = bytes.reverse
|
122
141
|
hex = bytes_reversed.reduce("0x") { |hex, byte| hex + byte.to_s(16).rjust(2, "0") }
|
123
|
-
new(hex.to_i(16))
|
142
|
+
result = new(hex.to_i(16))
|
143
|
+
|
144
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
145
|
+
|
146
|
+
result
|
124
147
|
end
|
125
148
|
end
|
126
149
|
|
@@ -142,9 +165,14 @@ module Scale
|
|
142
165
|
include SingleValue
|
143
166
|
# new(1.to_u32, U32(69))
|
144
167
|
module ClassMethods
|
168
|
+
def inherited(child)
|
169
|
+
child.const_set(:TYPE_NAME, child.name)
|
170
|
+
end
|
171
|
+
|
145
172
|
def decode(scale_bytes)
|
173
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
146
174
|
item_values = self::ITEM_TYPE_STRS.map do |item_type_str|
|
147
|
-
type = Scale::
|
175
|
+
type = Scale::Types.get(item_type_str)
|
148
176
|
type.decode(scale_bytes)
|
149
177
|
end
|
150
178
|
|
@@ -157,6 +185,7 @@ module Scale
|
|
157
185
|
value.each_pair do |attr, val|
|
158
186
|
result.send "#{attr}=", val
|
159
187
|
end
|
188
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
160
189
|
result
|
161
190
|
end
|
162
191
|
|
@@ -177,6 +206,7 @@ module Scale
|
|
177
206
|
|
178
207
|
def self.included(base)
|
179
208
|
base.extend ClassMethods
|
209
|
+
base.const_set(:TYPE_NAME, base.name)
|
180
210
|
end
|
181
211
|
|
182
212
|
def encode
|
@@ -193,9 +223,11 @@ module Scale
|
|
193
223
|
|
194
224
|
module ClassMethods
|
195
225
|
def decode(scale_bytes)
|
226
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
196
227
|
values = self::TYPE_STRS.map do |type_str|
|
197
228
|
Scale::Types.get(type_str).decode(scale_bytes)
|
198
229
|
end
|
230
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
199
231
|
new(values)
|
200
232
|
end
|
201
233
|
|
@@ -218,6 +250,7 @@ module Scale
|
|
218
250
|
|
219
251
|
module ClassMethods
|
220
252
|
def decode(scale_bytes)
|
253
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
221
254
|
index = scale_bytes.get_next_bytes(1)[0]
|
222
255
|
if const_defined? "ITEM_TYPE_STRS"
|
223
256
|
item_type_str = self::ITEM_TYPE_STRS[index]
|
@@ -226,7 +259,9 @@ module Scale
|
|
226
259
|
else
|
227
260
|
value = self::VALUES[index]
|
228
261
|
end
|
229
|
-
new(value)
|
262
|
+
result = new(value)
|
263
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
264
|
+
result
|
230
265
|
end
|
231
266
|
|
232
267
|
def items(items)
|
@@ -279,6 +314,7 @@ module Scale
|
|
279
314
|
|
280
315
|
module ClassMethods
|
281
316
|
def decode(scale_bytes, raw = false)
|
317
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
282
318
|
number = Scale::Types::Compact.decode(scale_bytes).value
|
283
319
|
items = []
|
284
320
|
number.times do
|
@@ -286,6 +322,7 @@ module Scale
|
|
286
322
|
item = type.decode(scale_bytes)
|
287
323
|
items << item
|
288
324
|
end
|
325
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
289
326
|
raw ? items : new(items)
|
290
327
|
end
|
291
328
|
|
@@ -313,10 +350,12 @@ module Scale
|
|
313
350
|
|
314
351
|
module ClassMethods
|
315
352
|
def decode(scale_bytes)
|
316
|
-
|
353
|
+
puts " BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
354
|
+
value = "Scale::Types::U#{self::BYTE_LENGTH * 8}".constantize2.decode(scale_bytes).value
|
317
355
|
return new [] unless value || value <= 0
|
318
356
|
|
319
357
|
result = self::ITEMS.select { |_, mask| value & mask > 0 }.keys
|
358
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
320
359
|
new result
|
321
360
|
end
|
322
361
|
|
@@ -340,7 +379,7 @@ module Scale
|
|
340
379
|
|
341
380
|
def encode
|
342
381
|
value = self.class::ITEMS.select { |key, _| self.value.include?(key) }.values.sum
|
343
|
-
"Scale::Types::U#{self.class::BYTE_LENGTH * 8}".
|
382
|
+
"Scale::Types::U#{self.class::BYTE_LENGTH * 8}".constantize2.new(value).encode
|
344
383
|
end
|
345
384
|
end
|
346
385
|
|
@@ -349,15 +388,17 @@ module Scale
|
|
349
388
|
|
350
389
|
module ClassMethods
|
351
390
|
def decode(scale_bytes)
|
352
|
-
|
353
|
-
|
354
|
-
byte_length
|
391
|
+
puts " BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
392
|
+
byte_length = self::BYTE_LENGTH
|
393
|
+
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)
|
355
394
|
|
356
395
|
bytes = scale_bytes.get_next_bytes(byte_length)
|
357
396
|
str = bytes.pack("C*").force_encoding("utf-8")
|
358
397
|
if str.valid_encoding?
|
398
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
359
399
|
new str
|
360
400
|
else
|
401
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
361
402
|
new bytes.bytes_to_hex
|
362
403
|
end
|
363
404
|
end
|
@@ -368,12 +409,10 @@ module Scale
|
|
368
409
|
end
|
369
410
|
|
370
411
|
def encode
|
371
|
-
|
372
|
-
length
|
373
|
-
raise "length is wrong: #{length}" unless %w[2 3 4 8 16 20 32 64].include?(length)
|
374
|
-
length = length.to_i
|
412
|
+
byte_length = self.class::BYTE_LENGTH
|
413
|
+
raise "#{self.class.name}'s byte length is wrong: #{byte_length}" unless %w[2 3 4 8 16 20 32 64 128 256].include?(byte_length.to_s)
|
375
414
|
|
376
|
-
if value.start_with?("0x") && value.length == (
|
415
|
+
if value.start_with?("0x") && value.length == (byte_length * 2 + 2)
|
377
416
|
value[2..]
|
378
417
|
else
|
379
418
|
bytes = value.unpack("C*")
|