scale.rb 0.2.13 → 0.2.18

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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}".constantize.decode(scale_bytes)
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 "substrate_common"
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
- attr_reader :spec_name, :types, :versioning, :custom_types
35
- attr_accessor :spec_version
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.nil? || spec_name == "default"
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] && @spec_version <= (item["runtime_range"][1] || 1073741823)
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.constantize) do
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" || type_str == "Option"
244
- klass = Class.new do
245
- include Scale::Types.type_of(type_str)
246
- inner_type inner_type_str
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
- klass = Class.new do
267
- include Scale::Types::Tuple
268
- inner_types *type_strs
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(&:camelize).join("_") : values.map(&:camelize).join("_")
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(&:camelize).join("_")}_#{klass.object_id}"
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(&:camelize).join("_")}_#{klass.object_id}"
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.constantize
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("<", "˂").gsub(">", "˃")
317
- .gsub("(", "").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::TypeRegistry.instance.get(item_type_str)
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
- value = "Scale::Types::U#{self::BYTE_LENGTH * 8}".constantize.decode(scale_bytes).value
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}".constantize.new(value).encode
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
- byte_length = name[25..]
353
- raise "length is wrong: #{byte_length}" unless %w[2 3 4 8 16 20 32 64].include?(byte_length)
354
- byte_length = byte_length.to_i
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
- class_name = self.class.to_s
372
- length = class_name[25..]
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 == (length * 2 + 2)
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*")