scale.rb 0.2.14 → 0.2.19

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.
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*")