scale_rb 0.4.1 → 0.5.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +21 -0
  3. data/Dockerfile +16 -0
  4. data/Gemfile +4 -4
  5. data/README.md +19 -6
  6. data/bin/console +0 -0
  7. data/bin/setup +0 -0
  8. data/examples/http_client_1.rb +0 -2
  9. data/examples/http_client_2.rb +0 -2
  10. data/examples/ws_client_1.rb +0 -2
  11. data/examples/ws_client_3.rb +1 -3
  12. data/examples/ws_client_4.rb +0 -2
  13. data/exe/metadata +9 -11
  14. data/lib/address.rb +1 -1
  15. data/lib/custom_assign.rb +92 -0
  16. data/lib/scale_rb/call_helper.rb +42 -0
  17. data/lib/{client → scale_rb/client}/client_ext.rb +12 -13
  18. data/lib/{client → scale_rb/client}/http_client.rb +3 -5
  19. data/lib/{client → scale_rb/client}/ws_client.rb +13 -20
  20. data/lib/scale_rb/codec.rb +25 -0
  21. data/lib/scale_rb/codec_utils.rb +128 -0
  22. data/lib/scale_rb/decode.rb +164 -0
  23. data/lib/scale_rb/encode.rb +150 -0
  24. data/lib/{hasher.rb → scale_rb/hasher.rb} +10 -8
  25. data/lib/scale_rb/metadata/metadata.rb +114 -0
  26. data/lib/{metadata → scale_rb/metadata}/metadata_v10.rb +0 -17
  27. data/lib/{metadata → scale_rb/metadata}/metadata_v11.rb +0 -17
  28. data/lib/{metadata → scale_rb/metadata}/metadata_v12.rb +0 -17
  29. data/lib/{metadata → scale_rb/metadata}/metadata_v13.rb +0 -17
  30. data/lib/{metadata → scale_rb/metadata}/metadata_v14.rb +18 -18
  31. data/lib/{metadata → scale_rb/metadata}/metadata_v9.rb +0 -17
  32. data/lib/scale_rb/metadata/registry.rb +263 -0
  33. data/lib/scale_rb/metadata/type_exp.rb +286 -0
  34. data/lib/scale_rb/portable_registry.rb +133 -0
  35. data/lib/{storage_helper.rb → scale_rb/storage_helper.rb} +16 -4
  36. data/lib/scale_rb/types.rb +233 -0
  37. data/lib/scale_rb/utils.rb +125 -0
  38. data/lib/scale_rb/version.rb +1 -1
  39. data/lib/scale_rb.rb +22 -30
  40. data/lib/type_enforcer.rb +170 -0
  41. data/scale_rb.gemspec +5 -0
  42. metadata +71 -19
  43. data/lib/codec.rb +0 -450
  44. data/lib/metadata/metadata.rb +0 -137
  45. data/lib/monkey_patching.rb +0 -115
  46. data/lib/portable_codec.rb +0 -285
  47. data/lib/registry.rb +0 -13
data/lib/codec.rb DELETED
@@ -1,450 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ScaleRb
4
- class Error < StandardError; end
5
- class NotImplemented < Error; end
6
- class NilTypeError < Error; end
7
- class TypeParseError < Error; end
8
- class NotEnoughBytesError < Error; end
9
- class InvalidBytesError < Error; end
10
- class Unreachable < Error; end
11
- class IndexOutOfRangeError < Error; end
12
- class LengthNotEqualErr < Error; end
13
- class InvalidValueError < Error; end
14
- end
15
-
16
- # TODO: set, bitvec
17
- module ScaleRb
18
- class << self
19
- def type_def?(type)
20
- type.instance_of?(String) && (
21
- bytes?(type) ||
22
- boolean?(type) ||
23
- string?(type) ||
24
- compact?(type) ||
25
- int?(type) ||
26
- uint?(type) ||
27
- option?(type) ||
28
- array?(type) ||
29
- vec?(type) ||
30
- tuple?(type)
31
- ) ||
32
- type.instance_of?(Hash)
33
- end
34
-
35
- def bytes?(type)
36
- type.downcase == 'bytes'
37
- end
38
-
39
- def boolean?(type)
40
- type.downcase == 'bool' || type.downcase == 'boolean'
41
- end
42
-
43
- def string?(type)
44
- type.downcase == 'str' || type.downcase == 'string' || type.downcase == 'text' || type.downcase == 'type'
45
- end
46
-
47
- def compact?(type)
48
- type.downcase == 'compact' ||
49
- (type[0..7].downcase == 'compact<' && type[-1] == '>')
50
- end
51
-
52
- def int?(type)
53
- type[0].downcase == 'i' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
54
- end
55
-
56
- def uint?(type)
57
- type[0].downcase == 'u' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
58
- end
59
-
60
- def option?(type)
61
- type[0..6].downcase == 'option<' && type[-1] == '>'
62
- end
63
-
64
- def array?(type)
65
- type[0] == '[' && type[-1] == ']'
66
- end
67
-
68
- def vec?(type)
69
- type[0..3].downcase == 'vec<' && type[-1] == '>'
70
- end
71
-
72
- def tuple?(type)
73
- type[0] == '(' && type[-1] == ')'
74
- end
75
-
76
- def struct?(type)
77
- type.instance_of?(Hash)
78
- end
79
-
80
- def enum?(type)
81
- type.instance_of?(Hash) && type.key?(:_enum)
82
- end
83
- end
84
- end
85
-
86
- module ScaleRb
87
- class << self
88
- def parse_option(type)
89
- type.scan(/\A[O|o]ption<(.+)>\z/).first.first
90
- end
91
-
92
- def parse_array(type)
93
- scan_out = type.scan(/\A\[\s*(.+)\s*;\s*(\d+)\s*\]\z/)
94
- raise ScaleRb::TypeParseError, type if scan_out.empty?
95
- raise ScaleRb::TypeParseError, type if scan_out[0].length != 2
96
-
97
- inner_type = scan_out[0][0]
98
- length = scan_out[0][1].to_i
99
- [inner_type, length]
100
- end
101
-
102
- def parse_vec(type)
103
- type.scan(/\A[V|v]ec<(.+)>\z/).first.first
104
- end
105
-
106
- def parse_tuple(type)
107
- type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
108
- end
109
- end
110
- end
111
-
112
- # Helper functions
113
- module ScaleRb
114
- class << self
115
- def _get_final_type_from_registry(registry, type)
116
- raise "Wrong lookup type #{type.class}" if !type.instance_of?(String) && !type.instance_of?(Hash)
117
-
118
- return if type.instance_of?(Hash)
119
-
120
- mapped = registry._get(type) # mapped: String(name, type_def) | Hash(type_def: struct, enum) | nil
121
-
122
- return if mapped.nil?
123
- return mapped if type_def?(mapped)
124
-
125
- _get_final_type_from_registry(registry, mapped)
126
- end
127
-
128
- def _decode_types(types, bytes, registry)
129
- _decode_each(types, bytes) do |type, remaining_bytes|
130
- decode(type, remaining_bytes, registry)
131
- end
132
- end
133
-
134
- def _decode_each(types, bytes, &decode)
135
- remaining_bytes = bytes
136
- values = types.map do |type|
137
- value, remaining_bytes = decode.call(type, remaining_bytes)
138
- value
139
- end
140
- [values, remaining_bytes]
141
- end
142
-
143
- def _do_decode_compact(bytes)
144
- case bytes[0] & 3
145
- when 0
146
- [bytes[0] >> 2, bytes[1..]]
147
- when 1
148
- [bytes[0..1]._flip._to_uint >> 2, bytes[2..]]
149
- when 2
150
- [bytes[0..3]._flip._to_uint >> 2, bytes[4..]]
151
- when 3
152
- length = 4 + (bytes[0] >> 2)
153
- [bytes[1..length]._flip._to_uint, bytes[length + 1..]]
154
- else
155
- raise Unreachable, 'type: Compact'
156
- end
157
- end
158
-
159
- def _encode_each(types, values, &encode)
160
- _encode_each_without_merge(types, values, &encode).flatten
161
- end
162
-
163
- def _encode_each_without_merge(types, values, &encode)
164
- raise LengthNotEqualErr, "types: #{types}, values: #{values.inspect}" if types.length != values.length
165
-
166
- types.map.with_index do |type, i|
167
- encode.call(type, values[i])
168
- end
169
- end
170
-
171
- def _encode_types(types, values, registry = {})
172
- _encode_each(types, values) do |type, value|
173
- encode(type, value, registry)
174
- end
175
- end
176
-
177
- def _encode_each_with_hashers(types, values, hashers, &encode)
178
- if !hashers.nil? && hashers.length != types.length
179
- raise ScaleRb::LengthNotEqualErr, "types length: #{types.length}, hashers length: #{hashers.length}"
180
- end
181
-
182
- bytes_array = ScaleRb._encode_each_without_merge(types, values, &encode)
183
- bytes_array.each_with_index.reduce([]) do |memo, (bytes, i)|
184
- memo + Hasher.apply_hasher(hashers[i], bytes)
185
- end
186
- end
187
- end
188
- end
189
-
190
- module ScaleRb
191
- # Decode
192
- class << self
193
- def decode(type, bytes, registry = {})
194
- # logger.debug '--------------------------------------------------'
195
- # debug 'decoding type', type
196
- # debug 'bytes', bytes&.length
197
-
198
- if type.instance_of?(String)
199
- return decode_bytes(bytes) if bytes?(type) # Bytes
200
- return decode_boolean(bytes) if boolean?(type) # Boolean
201
- return decode_string(bytes) if string?(type) # String
202
- return decode_int(type, bytes) if int?(type) # i8, i16...
203
- return decode_uint(type, bytes) if uint?(type) # u8, u16...
204
- return decode_compact(bytes) if compact?(type) # Compact<>
205
- return decode_option(type, bytes, registry) if option?(type) # Option<>
206
- return decode_array(type, bytes, registry) if array?(type) # [u8; 3]
207
- return decode_vec(type, bytes, registry) if vec?(type) # Vec<u8>
208
- return decode_tuple(type, bytes, registry) if tuple?(type) # (u8, u8)
209
-
210
- # search the type from registry if not the types above
211
- registry_type = _get_final_type_from_registry(registry, type)
212
- return decode(registry_type, bytes, registry) if registry_type
213
- elsif type.instance_of?(Hash)
214
- return decode_enum(type, bytes, registry) if enum?(type)
215
- return decode_struct(type, bytes, registry) if struct?(type)
216
- end
217
-
218
- raise NotImplemented, "type: #{type.inspect}"
219
- end
220
-
221
- def decode_bytes(bytes)
222
- length, remaining_bytes = _do_decode_compact(bytes)
223
- value = remaining_bytes[0...length]._to_hex
224
- # debug 'length', length
225
- # debug 'value', value
226
- [
227
- value,
228
- remaining_bytes[length..]
229
- ]
230
- end
231
-
232
- def decode_boolean(bytes)
233
- value =
234
- if bytes[0] == 0x00
235
- false
236
- elsif bytes[0] == 0x01
237
- true
238
- else
239
- raise InvalidBytesError, 'type: Boolean'
240
- end
241
- # debug 'value', value
242
- [value, bytes[1..]]
243
- end
244
-
245
- def decode_string(bytes)
246
- length, remaining_bytes = _do_decode_compact(bytes)
247
- raise NotEnoughBytesError, 'type: String' if remaining_bytes.length < length
248
-
249
- value = remaining_bytes[0...length]._to_utf8
250
- # debug 'byte length', length
251
- # debug 'value', value.inspect
252
- [
253
- value,
254
- remaining_bytes[length..]
255
- ]
256
- end
257
-
258
- def decode_int(type, bytes)
259
- bit_length = type[1..].to_i
260
- byte_length = bit_length / 8
261
- raise NotEnoughBytesError, "type: #{type}" if bytes.length < byte_length
262
-
263
- value = bytes[0...byte_length]._flip._to_int(bit_length)
264
- # debug 'value', value
265
- [
266
- value,
267
- bytes[byte_length..]
268
- ]
269
- end
270
-
271
- def decode_uint(type_def, bytes)
272
- bit_length = type_def[1..].to_i
273
- byte_length = bit_length / 8
274
- raise NotEnoughBytesError, "type: #{type_def}" if bytes.length < byte_length
275
-
276
- value = bytes[0...byte_length]._flip._to_uint
277
- # debug 'value', value
278
- [
279
- value,
280
- bytes[byte_length..]
281
- ]
282
- end
283
-
284
- def decode_compact(bytes)
285
- _do_decode_compact(bytes)
286
- # debug 'value', result[0]
287
- end
288
-
289
- def decode_option(type_def, bytes, registry = {})
290
- inner_type = parse_option(type_def)
291
-
292
- return [nil, bytes[1..]] if bytes[0] == 0x00
293
- return decode(inner_type, bytes[1..], registry) if bytes[0] == 0x01
294
-
295
- raise InvalidBytesError, "type: #{type_def}"
296
- end
297
-
298
- def decode_array(type_def, bytes, registry = {})
299
- inner_type, length = parse_array(type_def)
300
- _decode_types([inner_type] * length, bytes, registry)
301
- end
302
-
303
- def decode_vec(type_def, bytes, registry = {})
304
- inner_type = parse_vec(type_def)
305
- length, remaining_bytes = _do_decode_compact(bytes)
306
- # debug 'length', length
307
- _decode_types([inner_type] * length, remaining_bytes, registry)
308
- end
309
-
310
- def decode_tuple(type_def, bytes, registry = {})
311
- inner_types = parse_tuple(type_def)
312
- _decode_types(inner_types, bytes, registry)
313
- end
314
-
315
- # TODO: custom index?
316
- # {
317
- # _enum: {
318
- # name1: type1,
319
- # name2: type2
320
- # }
321
- # }
322
- # or
323
- # {
324
- # _enum: ['name1', 'name2']
325
- # }
326
- def decode_enum(type_def, bytes, registry = {})
327
- index = bytes[0]
328
-
329
- items = type_def[:_enum]
330
- raise IndexOutOfRangeError, "type: #{type_def}" if index > items.length - 1
331
-
332
- item = items.to_a[index] # 'name' or [:name, inner_type]
333
- # debug 'value', item.inspect
334
- return [item, bytes[1..]] if item.instance_of?(String)
335
-
336
- value, remaining_bytes = decode(item[1], bytes[1..], registry)
337
- [
338
- { item[0].to_sym => value },
339
- remaining_bytes
340
- ]
341
- end
342
-
343
- def decode_struct(struct, bytes, registry = {})
344
- values, remaining_bytes = _decode_types(struct.values, bytes, registry)
345
- [
346
- [struct.keys, values].transpose.to_h,
347
- remaining_bytes
348
- ]
349
- end
350
- end
351
-
352
- # Encode
353
- class << self
354
- def encode(type, value, registry = {})
355
- # logger.debug '--------------------------------------------------'
356
- # debug 'encoding type', type
357
- # debug 'value', value
358
-
359
- if type.instance_of?(String)
360
- return encode_bytes(value) if bytes?(type)
361
- return encode_boolean(value) if boolean?(type)
362
- return encode_string(value) if string?(type)
363
- return encode_compact(value) if compact?(type)
364
- return encode_uint(type, value) if uint?(type)
365
- return encode_option(type, value, registry) if option?(type)
366
- return encode_array(type, value, registry) if array?(type)
367
- return encode_vec(type, value, registry) if vec?(type)
368
- return encode_tuple(type, value, registry) if tuple?(type)
369
-
370
- registry_type = _get_final_type_from_registry(registry, type)
371
- return encode(registry_type, value, registry) if registry_type
372
- elsif type.instance_of?(Hash)
373
- return encode_enum(type, value, registry) if enum?(type)
374
- return encode_struct(type, value, registry) if struct?(type)
375
- end
376
-
377
- raise NotImplemented, "type: #{type}, value: #{value.inspect}"
378
- end
379
-
380
- def encode_bytes(value)
381
- encode_compact(value.length) + value
382
- end
383
-
384
- def encode_boolean(value)
385
- return [0x00] if value == false
386
- return [0x01] if value == true
387
-
388
- raise InvalidValueError, "type: Boolean, value: #{value.inspect}"
389
- end
390
-
391
- def encode_string(string)
392
- body = string.unpack('C*')
393
- prefix = encode_compact(body.length)
394
- prefix + body
395
- end
396
-
397
- def encode_compact(value)
398
- return [value << 2] if (value >= 0) && (value < 64)
399
- return ((value << 2) + 1)._to_bytes._flip if value < 2**14
400
- return ((value << 2) + 2)._to_bytes._flip if value < 2**30
401
-
402
- bytes = value._to_bytes._flip
403
- [(((bytes.length - 4) << 2) + 3)] + bytes
404
- end
405
-
406
- def encode_uint(type, value)
407
- raise InvalidValueError, "type: #{type}, value: #{value.inspect}" unless value.instance_of?(Integer)
408
-
409
- bit_length = type[1..].to_i
410
- value._to_bytes(bit_length)._flip
411
- end
412
-
413
- def encode_option(type, value, registry = {})
414
- return [0x00] if value.nil?
415
-
416
- inner_type = type.scan(/\A[O|o]ption<(.+)>\z/).first.first
417
- [0x01] + encode(inner_type, value, registry)
418
- end
419
-
420
- def encode_array(type, array, registry = {})
421
- inner_type, length = parse_array(type)
422
- raise LengthNotEqualErr, "type: #{type}, value: #{array.inspect}" if length != array.length
423
-
424
- _encode_types([inner_type] * length, array, registry)
425
- end
426
-
427
- def encode_vec(type, array, registry = {})
428
- inner_type = type.scan(/\A[V|v]ec<(.+)>\z/).first.first
429
- length_bytes = encode_compact(array.length)
430
- length_bytes + _encode_types([inner_type] * array.length, array, registry)
431
- end
432
-
433
- def encode_tuple(tuple_type, tuple, registry = {})
434
- inner_types = tuple_type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
435
- _encode_types(inner_types, tuple, registry)
436
- end
437
-
438
- def encode_enum(enum_type, enum, registry = {})
439
- key = enum.keys.first
440
- value = enum.values.first
441
- value_type = enum_type[:_enum][key]
442
- index = enum_type[:_enum].keys.index(key)
443
- encode_uint('u8', index) + encode(value_type, value, registry)
444
- end
445
-
446
- def encode_struct(struct_type, struct, registry = {})
447
- _encode_types(struct_type.values, struct.values, registry)
448
- end
449
- end
450
- end
@@ -1,137 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ScaleRb
4
- module Metadata
5
- class << self
6
- def decode_metadata(bytes)
7
- metadata, = ScaleRb.decode('MetadataTop', bytes, TYPES)
8
- metadata
9
- end
10
-
11
- def build_registry(metadata)
12
- raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless metadata._get(:metadata)._key?(:v14)
13
-
14
- metadata_v14 = metadata._get(:metadata)._get(:v14)
15
- MetadataV14.build_registry(metadata_v14)
16
- end
17
-
18
- def get_module(pallet_name, metadata)
19
- version = metadata._get(:metadata).keys.first
20
- raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
21
- v14].include?(version.to_s)
22
-
23
- Metadata.const_get("Metadata#{version.upcase}").get_module(pallet_name, metadata)
24
- end
25
-
26
- def get_module_by_index(pallet_index, metadata)
27
- version = metadata._get(:metadata).keys.first
28
- raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
29
- v14].include?(version.to_s)
30
-
31
- Metadata.const_get("Metadata#{version.upcase}").get_module_by_index(pallet_index, metadata)
32
- end
33
-
34
- def get_storage_item(pallet_name, item_name, metadata)
35
- version = metadata._get(:metadata).keys.first
36
- raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
37
- v14].include?(version.to_s)
38
-
39
- Metadata.const_get("Metadata#{version.upcase}").get_storage_item(pallet_name, item_name, metadata)
40
- end
41
-
42
- def get_calls_type(pallet_name, metadata)
43
- version = metadata._get(:metadata).keys.first
44
- raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
45
- v14].include?(version.to_s)
46
-
47
- Metadata.const_get("Metadata#{version.upcase}").get_calls_type(pallet_name, metadata)
48
- end
49
-
50
- def get_calls_type_id(pallet_name, metadata)
51
- version = metadata._get(:metadata).keys.first
52
- raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
53
- v14].include?(version.to_s)
54
-
55
- Metadata.const_get("Metadata#{version.upcase}").get_calls_type_id(pallet_name, metadata)
56
- end
57
-
58
- def get_call_type(pallet_name, call_name, metadata)
59
- version = metadata._get(:metadata).keys.first
60
- raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
61
- v14].include?(version.to_s)
62
-
63
- Metadata.const_get("Metadata#{version.upcase}").get_call_type(pallet_name, call_name, metadata)
64
- end
65
-
66
- # call examples:
67
- # {:pallet_name=>"Deposit", :call_name=>"Claim", :call=>["claim", []]}
68
- # {:pallet_name=>"Balances", :call_name=>"Transfer", :call=>[{:transfer=>{:dest=>[10, 18, 135, 151, 117, 120, 248, 136, 189, 193, 199, 98, 119, 129, 175, 28, 192, 0, 230, 171], :value=>11000000000000000000}}, []]}
69
- def encode_call(call, metadata)
70
- calls_type_id = get_calls_type_id(call[:pallet_name], metadata)
71
- pallet_index = get_module(call[:pallet_name], metadata)._get(:index)
72
- [pallet_index] + PortableCodec.encode(calls_type_id, call[:call].first, build_registry(metadata))
73
- end
74
-
75
- # callbytes's structure is: pallet_index + call_index + argsbytes
76
- #
77
- # callbytes examples:
78
- # "0x0901"._to_bytes
79
- # "0x05000a1287977578f888bdc1c7627781af1cc000e6ab1300004c31b8d9a798"._to_bytes
80
- def decode_call(callbytes, metadata)
81
- pallet_index = callbytes[0]
82
- pallet = get_module_by_index(pallet_index, metadata)
83
-
84
- pallet_name = pallet._get(:name)
85
-
86
- # Remove the pallet_index
87
- # The callbytes we used below should not contain the pallet index.
88
- # This is because the pallet index is not part of the call type.
89
- # Its structure is: call_index + call_args
90
- callbytes_without_pallet_index = callbytes[1..]
91
- calls_type_id = pallet._get(:calls)._get(:type)
92
- decoded = PortableCodec.decode(
93
- calls_type_id,
94
- callbytes_without_pallet_index,
95
- build_registry(metadata)
96
- )
97
-
98
- {
99
- pallet_name: pallet_name,
100
- call_name: decoded.first.is_a?(String) ? decoded.first._to_camel : decoded.first.keys.first.to_s._to_camel,
101
- call: decoded
102
- }
103
- end
104
- end
105
-
106
- TYPES = {
107
- 'MetadataTop' => {
108
- magicNumber: 'U32',
109
- metadata: 'Metadata'
110
- },
111
- 'Metadata' => {
112
- _enum: {
113
- v0: 'MetadataV0',
114
- v1: 'MetadataV1',
115
- v2: 'MetadataV2',
116
- v3: 'MetadataV3',
117
- v4: 'MetadataV4',
118
- v5: 'MetadataV5',
119
- v6: 'MetadataV6',
120
- v7: 'MetadataV7',
121
- v8: 'MetadataV8',
122
- v9: 'MetadataV9',
123
- v10: 'MetadataV10',
124
- v11: 'MetadataV11',
125
- v12: 'MetadataV12',
126
- v13: 'MetadataV13',
127
- v14: 'MetadataV14'
128
- }
129
- }
130
- }.merge(MetadataV14::TYPES)
131
- .merge(MetadataV13::TYPES)
132
- .merge(MetadataV12::TYPES)
133
- .merge(MetadataV11::TYPES)
134
- .merge(MetadataV10::TYPES)
135
- .merge(MetadataV9::TYPES)
136
- end
137
- end
@@ -1,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # https://www.rubyguides.com/2017/01/read-binary-data/
4
- class String
5
- def _to_bytes
6
- data = start_with?('0x') ? self[2..] : self
7
- raise 'Not valid hex string' if data =~ /[^\da-f]+/i
8
-
9
- data = "0#{data}" if data.length.odd?
10
- data.scan(/../).map(&:hex)
11
- end
12
-
13
- def _to_camel
14
- split('_').collect(&:capitalize).join
15
- end
16
-
17
- def _underscore
18
- gsub(/::/, '/')
19
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
20
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
21
- .tr('-', '_')
22
- .downcase
23
- end
24
- end
25
-
26
- class Integer
27
- def _to_bytes(bit_length = nil)
28
- return to_s(16)._to_bytes unless bit_length
29
-
30
- hex = to_s(16).rjust(bit_length / 4, '0')
31
- hex._to_bytes
32
- end
33
-
34
- # unsigned to signed
35
- def _to_signed(bit_length)
36
- unsigned_mid = 2**(bit_length - 1)
37
- unsigned_ceiling = 2**bit_length
38
- self >= unsigned_mid ? self - unsigned_ceiling : self
39
- end
40
-
41
- # signed to unsigned
42
- def _to_unsigned(bit_length)
43
- unsigned_mid = 2**(bit_length - 1)
44
- unsigned_ceiling = 2**bit_length
45
- raise 'out of scope' if self >= unsigned_mid || self <= -unsigned_mid
46
-
47
- negative? ? unsigned_ceiling + self : self
48
- end
49
-
50
- # unix timestamp to utc
51
- def _to_utc
52
- Time.at(self).utc.asctime
53
- end
54
-
55
- # utc to unix timestamp
56
- def _from_utc(utc_asctime)
57
- Time.parse(utc_asctime)
58
- end
59
- end
60
-
61
- class Array
62
- def _to_hex
63
- raise 'Not a byte array' unless _byte_array?
64
-
65
- reduce('0x') { |hex, byte| hex + byte.to_s(16).rjust(2, '0') }
66
- end
67
-
68
- def _to_bin
69
- raise 'Not a byte array' unless _byte_array?
70
-
71
- reduce('0b') { |bin, byte| bin + byte.to_s(2).rjust(8, '0') }
72
- end
73
-
74
- def _to_utf8
75
- raise 'Not a byte array' unless _byte_array?
76
-
77
- pack('C*').force_encoding('utf-8')
78
- end
79
-
80
- def _to_uint
81
- _to_hex.to_i(16)
82
- end
83
-
84
- def _to_int(bit_length)
85
- _to_uint._to_signed(bit_length)
86
- end
87
-
88
- def _flip
89
- reverse
90
- end
91
-
92
- def _byte_array?
93
- all? { |e| e >= 0 and e <= 255 }
94
- end
95
- end
96
-
97
- class Hash
98
- def _key?(key)
99
- if key.instance_of?(String)
100
- key?(key) || key?(key.to_sym)
101
- else
102
- key?(key) || key?(key.to_s)
103
- end
104
- end
105
-
106
- def _get(key)
107
- if key.instance_of?(String)
108
- self[key] || self[key.to_sym]
109
- elsif key.instance_of?(Symbol)
110
- self[key] || self[key.to_s]
111
- else
112
- self[key]
113
- end
114
- end
115
- end