abi_coder_rb 0.1.0 → 0.2.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.
@@ -0,0 +1,669 @@
1
+ # Generated from https://github.com/wuminzhe/abi_coder_rb
2
+ module AbiCoderRb
3
+ def decode_array(type, data)
4
+ size = decode_uint256(data[0, 32])
5
+ raise DecodingError, "Too many elements: #{size}" if size > 100_000
6
+ subtype = type.subtype
7
+ if subtype.dynamic?
8
+ raise DecodingError, "Not enough data for head" unless data.size >= 32 + 32 * size
9
+ start_positions = (1..size).map { |i| 32 + decode_uint256(data[32 * i, 32]) }
10
+ start_positions.push(data.size)
11
+ outputs = (0...size).map { |i| data[start_positions[i]...start_positions[i + 1]] }
12
+ outputs.map { |out| decode_type(subtype, out) }
13
+ else
14
+ (0...size).map { |i| decode_type(subtype, data[(32 + subtype.size * i)..]) }
15
+ end
16
+ end
17
+ end
18
+ module AbiCoderRb
19
+ def decode_fixed_array(type, data)
20
+ l = type.dim
21
+ subtype = type.subtype
22
+ if subtype.dynamic?
23
+ start_positions = (0...l).map { |i| decode_uint256(data[32 * i, 32]) }
24
+ start_positions.push(data.size)
25
+ outputs = (0...l).map { |i| data[start_positions[i]...start_positions[i + 1]] }
26
+ outputs.map { |out| decode_type(subtype, out) }
27
+ else
28
+ (0...l).map { |i| decode_type(subtype, data[subtype.size * i, subtype.size]) }
29
+ end
30
+ end
31
+ end
32
+ module AbiCoderRb
33
+ def decode_primitive_type(type, data)
34
+ result =
35
+ case type
36
+ when Uint
37
+ decode_uint256(data[0, 32])
38
+ when Int
39
+ Utils.abi_to_int_signed(bin_to_hex(data[0, 32]), type.bits)
40
+ when Bool
41
+ data[31] == BYTE_ONE
42
+ when String
43
+ size = decode_uint256(data[0, 32])
44
+ data[32...(32 + size)].force_encoding("UTF-8")
45
+ when Bytes
46
+ size = decode_uint256(data[0, 32])
47
+ data[32...(32 + size)]
48
+ when FixedBytes
49
+ data[0, type.length]
50
+ when Address
51
+ bin_to_hex(data[12...32]).force_encoding("UTF-8")
52
+ else
53
+ raise DecodingError, "Unknown primitive type: #{type.class.name} #{type.format}"
54
+ end
55
+ result = after_decoding_action.call(type.format, result) if after_decoding_action
56
+ result
57
+ end
58
+ private
59
+ def decode_uint256(bin)
60
+ bin_to_hex(bin).to_i(16)
61
+ end
62
+ end
63
+ module AbiCoderRb
64
+ def decode_tuple(type, data)
65
+ decode_types(type.types, data)
66
+ end
67
+ private
68
+ def decode_types(types, data)
69
+ start_positions = start_positions(types, data)
70
+ types.map.with_index do |type, index|
71
+ start_position = start_positions[index]
72
+ decode_type(type, data[start_position..])
73
+ end
74
+ end
75
+ def start_positions(types, data)
76
+ start_positions = ::Array.new(types.size)
77
+ offset = 0
78
+ types.each_with_index do |type, index|
79
+ if type.dynamic?
80
+ start_positions[index] = decode_uint256(data[offset, 32])
81
+ offset += 32
82
+ else
83
+ start_positions[index] = offset
84
+ offset += type.size
85
+ end
86
+ end
87
+ start_positions
88
+ end
89
+ end
90
+ module AbiCoderRb
91
+ def decode(type_str, data)
92
+ raise DecodingError, "Empty data" if data.nil? || data.empty?
93
+ decode_type(Type.parse(type_str), data)
94
+ end
95
+ private
96
+ def decode_type(type, data)
97
+ case type
98
+ when Tuple ## todo: support empty (unit) tuple - why? why not?
99
+ decode_tuple(type, data)
100
+ when FixedArray # static-sized arrays
101
+ decode_fixed_array(type, data)
102
+ when Array
103
+ decode_array(type, data)
104
+ else
105
+ decode_primitive_type(type, data)
106
+ end
107
+ end
108
+ end
109
+ module AbiCoderRb
110
+ def encode_array(type, args)
111
+ raise ArgumentError, "arg must be an array" unless args.is_a?(::Array)
112
+ head = "".b
113
+ tail = "".b # 使用二进制字符串
114
+ head += encode_uint256(args.size)
115
+ subtype = type.subtype
116
+ args.each do |arg|
117
+ if subtype.dynamic?
118
+ head += encode_uint256(32 * args.size + tail.size)
119
+ tail += encode_type(subtype, arg)
120
+ else
121
+ head += encode_type(subtype, arg)
122
+ end
123
+ end
124
+ head + tail
125
+ end
126
+ end
127
+ module AbiCoderRb
128
+ def encode_fixed_array(type, args)
129
+ raise ArgumentError, "arg must be an array" unless args.is_a?(::Array)
130
+ raise ArgumentError, "Wrong array size: found #{args.size}, expecting #{type.dim}" unless args.size == type.dim
131
+ subtype = type.subtype
132
+ if subtype.dynamic?
133
+ head = "".b
134
+ tail = "".b
135
+ args.each do |arg|
136
+ head += encode_uint256(32 * args.size + tail.size)
137
+ tail += encode_type(subtype, arg)
138
+ end
139
+ head + tail
140
+ else
141
+ args.map { |arg| encode_type(type.subtype, arg) }.join
142
+ end
143
+ end
144
+ end
145
+ module AbiCoderRb
146
+ def encode_primitive_type(type, arg)
147
+ arg = before_encoding_action.call(type.format, arg) if before_encoding_action
148
+ case type
149
+ when Uint
150
+ encode_uint(arg, type.bits)
151
+ when Int
152
+ encode_int(arg, type.bits)
153
+ when Bool
154
+ encode_bool(arg)
155
+ when String
156
+ encode_string(arg)
157
+ when FixedBytes
158
+ encode_bytes(arg, type.length)
159
+ when Bytes
160
+ encode_bytes(arg)
161
+ when Address
162
+ encode_address(arg)
163
+ else
164
+ raise EncodingError, "Unknown type: #{type}"
165
+ end
166
+ end
167
+ def encode_uint(arg, bits)
168
+ raise ArgumentError, "arg is not integer: #{arg}" unless arg.is_a?(Integer)
169
+ raise ValueOutOfBounds, arg unless arg >= 0 && arg < 2**bits
170
+ lpad_int(arg)
171
+ end
172
+ def encode_uint256(arg)
173
+ encode_uint(arg, 256)
174
+ end
175
+ def encode_int(arg, _bits)
176
+ raise ArgumentError, "arg is not integer: #{arg}" unless arg.is_a?(Integer)
177
+ hex_to_bin(Utils.int_to_abi_signed_256bit(arg))
178
+ end
179
+ def encode_bool(arg)
180
+ raise ArgumentError, "arg is not bool: #{arg}" unless arg.is_a?(TrueClass) || arg.is_a?(FalseClass)
181
+ lpad(arg ? BYTE_ONE : BYTE_ZERO) ## was lpad_int( arg ? 1 : 0 )
182
+ end
183
+ def encode_string(arg)
184
+ raise EncodingError, "Expecting string: #{arg}" unless arg.is_a?(::String)
185
+ arg = arg.b if arg.encoding != "BINARY" ## was: name == 'UTF-8', wasm
186
+ raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size > UINT_MAX
187
+ size = lpad_int(arg.size)
188
+ value = rpad(arg, ceil32(arg.size))
189
+ size + value
190
+ end
191
+ def encode_bytes(arg, length = nil)
192
+ raise EncodingError, "Expecting string: #{arg}" unless arg.is_a?(::String)
193
+ arg = arg.b if arg.encoding != Encoding::BINARY
194
+ if length # fixed length type
195
+ raise ValueOutOfBounds, "invalid bytes length #{arg.size}, should be #{length}" if arg.size > length
196
+ raise ValueOutOfBounds, "invalid bytes length #{length}" if length < 0 || length > 32
197
+ rpad(arg)
198
+ else # variable length type (if length is nil)
199
+ raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size > UINT_MAX
200
+ size = lpad_int(arg.size)
201
+ value = rpad(arg, ceil32(arg.size))
202
+ size + value
203
+ end
204
+ end
205
+ def encode_address(arg)
206
+ if arg.is_a?(Integer)
207
+ lpad_int(arg)
208
+ elsif arg.size == 20
209
+ arg = arg.b if arg.encoding != Encoding::BINARY
210
+ lpad(arg)
211
+ elsif arg.size == 40
212
+ lpad_hex(arg)
213
+ elsif arg.size == 42 && arg[0, 2] == "0x" ## todo/fix: allow 0X too - why? why not?
214
+ lpad_hex(arg[2..-1])
215
+ else
216
+ raise EncodingError, "Could not parse address: #{arg}"
217
+ end
218
+ end
219
+ private
220
+ def int_to_eth_abi(value, bits)
221
+ value = 2**bits + value if value < 0
222
+ hex = (value % 2**bits).to_s(16)
223
+ hex = "0#{hex}" if hex.length.odd?
224
+ hex.rjust(bits / 4, "0")
225
+ end
226
+ def rpad(bin, l = 32) ## note: same as builtin String#ljust !!!
227
+ return bin if bin.size >= l
228
+ bin + BYTE_ZERO * (l - bin.size)
229
+ end
230
+ def lpad(bin) ## note: same as builtin String#rjust !!!
231
+ l = 32 # NOTE: default l word is 32 bytes
232
+ return bin if bin.size >= l
233
+ BYTE_ZERO * (l - bin.size) + bin
234
+ end
235
+ def lpad_int(n)
236
+ raise ArgumentError, "Integer invalid or out of range: #{n}" unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
237
+ hex = n.to_s(16)
238
+ hex = "0#{hex}" if hex.length.odd? # wasm, no .odd?
239
+ bin = hex_to_bin(hex)
240
+ lpad(bin)
241
+ end
242
+ def lpad_hex(hex)
243
+ raise TypeError, "Value must be a string" unless hex.is_a?(::String)
244
+ raise TypeError, "Non-hexadecimal digit found" unless hex =~ /\A[0-9a-fA-F]*\z/
245
+ bin = hex_to_bin(hex)
246
+ lpad(bin)
247
+ end
248
+ def ceil32(x)
249
+ x % 32 == 0 ? x : (x + 32 - x % 32)
250
+ end
251
+ end
252
+ module AbiCoderRb
253
+ def encode_tuple(tuple, args)
254
+ encode_types(tuple.types, args)
255
+ end
256
+ private
257
+ def encode_types(types, args)
258
+ raise ArgumentError, "args must be an array" unless args.is_a?(::Array)
259
+ unless args.size == types.size
260
+ raise ArgumentError,
261
+ "Wrong number of args: found #{args.size}, expecting #{types.size}"
262
+ end
263
+ head_size = types.map { |type| type.size || 32 }.sum
264
+ head = "".b
265
+ tail = "".b # 使用二进制字符串
266
+ types.each_with_index do |type, i|
267
+ if type.dynamic?
268
+ head += encode_uint256(head_size + tail.size)
269
+ tail += encode_type(type, args[i])
270
+ else
271
+ head += encode_type(type, args[i])
272
+ end
273
+ end
274
+ head + tail
275
+ end
276
+ end
277
+ module AbiCoderRb
278
+ def encode(type, value)
279
+ raise EncodingError, "Value can not be nil" if value.nil?
280
+ parsed = Type.parse(type)
281
+ encode_type(parsed, value)
282
+ end
283
+ private
284
+ def encode_type(type, value)
285
+ if type.is_a?(Tuple)
286
+ encode_tuple(type, value)
287
+ elsif type.is_a?(Array)
288
+ encode_array(type, value)
289
+ elsif type.is_a?(FixedArray)
290
+ encode_fixed_array(type, value)
291
+ else
292
+ encode_primitive_type(type, value)
293
+ end
294
+ end
295
+ end
296
+ module AbiCoderRb
297
+ class Type
298
+ class ParseError < StandardError; end
299
+ class Parser
300
+ TUPLE_TYPE_RX = /^\((.*)\)
301
+ ((\[[0-9]*\])*)
302
+ /x
303
+ def self.parse(type)
304
+ type = type.strip
305
+ if type =~ TUPLE_TYPE_RX
306
+ types = _parse_tuple_type(::Regexp.last_match(1))
307
+ dims = _parse_dims(::Regexp.last_match(2))
308
+ parsed_types = types.map { |t| parse(t) }
309
+ return _parse_array_type(Tuple.new(parsed_types), dims)
310
+ end
311
+ base, sub, dims = _parse_base_type(type)
312
+ sub ||= 256 if type.start_with?("uint") || type.start_with?("int") # default to 256 if no sub given
313
+ _validate_base_type(base, sub)
314
+ subtype = case base
315
+ when "string" then String.new
316
+ when "bytes" then sub ? FixedBytes.new(sub) : Bytes.new
317
+ when "uint" then Uint.new(sub)
318
+ when "int" then Int.new(sub)
319
+ when "address" then Address.new
320
+ when "bool" then Bool.new
321
+ else
322
+ raise ParseError, "Unrecognized type base: #{base}"
323
+ end
324
+ _parse_array_type(subtype, dims)
325
+ end
326
+ BASE_TYPE_RX = /([a-z]*)
327
+ ([0-9]*)
328
+ ((\[[0-9]*\])*)
329
+ /x
330
+ def self._parse_base_type(str)
331
+ _, base, subscript, dimension = BASE_TYPE_RX.match(str).to_a
332
+ sub = subscript == "" ? nil : subscript.to_i
333
+ dims = _parse_dims(dimension)
334
+ [base, sub, dims]
335
+ end
336
+ def self._parse_dims(str)
337
+ dims = str.scan(/\[[0-9]*\]/)
338
+ dims.map do |dim|
339
+ size = dim[1...-1]
340
+ size == "" ? -1 : size.to_i
341
+ end
342
+ end
343
+ def self._parse_array_type(subtype, dims)
344
+ dims.each do |dim|
345
+ subtype = if dim == -1
346
+ Array.new(subtype)
347
+ else
348
+ FixedArray.new(subtype, dim)
349
+ end
350
+ end
351
+ subtype
352
+ end
353
+ def self._validate_base_type(base, sub)
354
+ case base
355
+ when "string"
356
+ raise ParseError, "String cannot have suffix" if sub
357
+ when "bytes"
358
+ raise ParseError, "Maximum 32 bytes for fixed-length bytes" if sub && sub > 32
359
+ when "uint", "int"
360
+ raise ParseError, "Integer type must have numerical suffix" unless sub
361
+ raise ParseError, "Integer size out of bounds" unless sub >= 8 && sub <= 256
362
+ raise ParseError, "Integer size must be multiple of 8" unless sub % 8 == 0
363
+ when "address"
364
+ raise ParseError, "Address cannot have suffix" if sub
365
+ when "bool"
366
+ raise ParseError, "Bool cannot have suffix" if sub
367
+ else
368
+ raise ParseError, "Unrecognized type base: #{base}"
369
+ end
370
+ end
371
+ def self._parse_tuple_type(str)
372
+ depth = 0
373
+ collected = []
374
+ current = ""
375
+ str.each_char do |c|
376
+ case c
377
+ when ","
378
+ if depth == 0
379
+ collected << current
380
+ current = ""
381
+ else
382
+ current += c
383
+ end
384
+ when "("
385
+ depth += 1
386
+ current += c
387
+ when ")"
388
+ depth -= 1
389
+ current += c
390
+ else
391
+ current += c
392
+ end
393
+ end
394
+ collected << current unless current.empty?
395
+ collected
396
+ end
397
+ end # class Parser
398
+ end # class Type
399
+ end # module ABI
400
+ module AbiCoderRb
401
+ class Type
402
+ def self.parse(type) ## convenience helper
403
+ Parser.parse(type)
404
+ end
405
+ def size
406
+ end
407
+ def dynamic?
408
+ size.nil?
409
+ end
410
+ def format
411
+ end
412
+ end
413
+ class Address < Type
414
+ def size
415
+ 32
416
+ end
417
+ def format
418
+ "address"
419
+ end
420
+ def ==(other)
421
+ other.is_a?(Address)
422
+ end
423
+ end # class Address
424
+ class Bytes < Type
425
+ def size
426
+ nil
427
+ end
428
+ def format
429
+ "bytes"
430
+ end
431
+ def ==(other)
432
+ other.is_a?(Bytes)
433
+ end
434
+ end # class Bytes
435
+ class FixedBytes < Type
436
+ attr_reader :length
437
+ def initialize(length)
438
+ @length = length # in bytes (1,2,...32)
439
+ end
440
+ def size
441
+ 32
442
+ end
443
+ def format
444
+ "bytes#{@length}"
445
+ end
446
+ def ==(other)
447
+ other.is_a?(FixedBytes) && @length == other.length
448
+ end
449
+ end # class FixedBytes
450
+ class Int < Type
451
+ attr_reader :bits
452
+ def initialize(bits = 256)
453
+ @bits = bits # in bits (8,16,...256)
454
+ end
455
+ def size
456
+ 32
457
+ end
458
+ def format
459
+ "int#{@bits}"
460
+ end
461
+ def ==(other)
462
+ other.is_a?(Int) && @bits == other.bits
463
+ end
464
+ end # class Int
465
+ class Uint < Type
466
+ attr_reader :bits
467
+ def initialize(bits = 256)
468
+ @bits = bits # in bits (8,16,...256)
469
+ end
470
+ def size
471
+ 32
472
+ end
473
+ def format
474
+ "uint#{@bits}"
475
+ end
476
+ def ==(other)
477
+ other.is_a?(Uint) && @bits == other.bits
478
+ end
479
+ end # class Uint
480
+ class Bool < Type
481
+ def size
482
+ 32
483
+ end
484
+ def format
485
+ "bool"
486
+ end
487
+ def ==(other)
488
+ other.is_a?(Bool)
489
+ end
490
+ end # class Bool
491
+ class String < Type
492
+ def size
493
+ nil
494
+ end
495
+ def format
496
+ "string"
497
+ end
498
+ def ==(other)
499
+ other.is_a?(String)
500
+ end
501
+ end # class String
502
+ class Array < Type
503
+ attr_reader :subtype
504
+ def initialize(subtype)
505
+ @subtype = subtype
506
+ end
507
+ def size
508
+ nil
509
+ end
510
+ def format
511
+ "#{@subtype.format}[]"
512
+ end
513
+ def ==(other)
514
+ other.is_a?(Array) && @subtype == other.subtype
515
+ end
516
+ end # class Array
517
+ class FixedArray < Type
518
+ attr_reader :subtype, :dim
519
+ def initialize(subtype, dim)
520
+ @subtype = subtype
521
+ @dim = dim
522
+ end
523
+ def size
524
+ @subtype.dynamic? ? nil : @dim * subtype.size
525
+ end
526
+ def format
527
+ "#{@subtype.format}[#{@dim}]"
528
+ end
529
+ def ==(other)
530
+ other.is_a?(FixedArray) &&
531
+ @dim == other.dim &&
532
+ @subtype == other.subtype
533
+ end
534
+ end # class FixedArray
535
+ class Tuple < Type
536
+ attr_reader :types
537
+ def initialize(types)
538
+ @types = types
539
+ end
540
+ def size
541
+ s = 0
542
+ has_dynamic = false
543
+ @types.each do |type|
544
+ ts = type.size
545
+ if ts.nil?
546
+ has_dynamic = true
547
+ else
548
+ s += ts
549
+ end
550
+ end
551
+ return if has_dynamic
552
+ s
553
+ end
554
+ def format
555
+ "(#{@types.map { |t| t.format }.join(",")})" ## rebuild minimal string
556
+ end
557
+ def ==(other)
558
+ other.is_a?(Tuple) && @types == other.types
559
+ end
560
+ end # class Tuple
561
+ end # module ABI
562
+ module AbiCoderRb
563
+ module Utils
564
+ class << self
565
+ def hex_to_bin(hex)
566
+ hex = hex[2..] if %w[0x 0X].include?(hex[0, 2]) ## cut-of leading 0x or 0X if present
567
+ hex.scan(/../).map { |x| x.hex.chr }.join
568
+ end
569
+ def bin_to_hex(bin)
570
+ bin.each_byte.map { |byte| "%02x" % byte }.join
571
+ end
572
+ def hex?(str)
573
+ str.start_with?("0x") && str.length.even? && str[2..].match?(/\A\b[0-9a-fA-F]+\b\z/)
574
+ end
575
+ def lpad(str, sym, len)
576
+ return str if str.size >= len
577
+ sym * (len - str.size) + str
578
+ end
579
+ def zpad(str, len)
580
+ lpad str, BYTE_ZERO, len
581
+ end
582
+ def ffpad(str, len)
583
+ lpad str, BYTE_FF, len
584
+ end
585
+ def uint_to_big_endian(num, size)
586
+ raise "Can only serialize integers" unless num.is_a?(Integer)
587
+ raise "Cannot serialize negative integers" if num.negative?
588
+ raise "Integer too large (does not fit in #{size} bytes)" if size && num >= 256**size
589
+ s = if num.zero?
590
+ BYTE_EMPTY
591
+ else
592
+ hex = num.to_s(16)
593
+ hex = "0#{hex}" if hex.size.odd?
594
+ hex_to_bin hex
595
+ end
596
+ s = size ? "#{BYTE_ZERO * [0, size - s.size].max}#{s}" : s
597
+ zpad s, size
598
+ end
599
+ def int_to_abi_signed_256bit(value)
600
+ min = -2**255
601
+ max = 2**255 - 1
602
+ raise "Value out of range" if value < min || value > max
603
+ value = (1 << 256) + value if value < 0
604
+ hex_str = value.to_s(16)
605
+ hex_str.rjust(64, "0")
606
+ end
607
+ def int_to_abi_signed(value)
608
+ raise "Value out of range" if value < -2**31 || value > 2**31 - 1
609
+ hex_str = [value].pack("l>").unpack1("H*")
610
+ if value >= 0
611
+ hex_str.rjust(64, "0")
612
+ else
613
+ hex_str.rjust(64, "f")
614
+ end
615
+ end
616
+ def abi_to_int_signed(hex_str, bits)
617
+ hex_str = "0x#{hex_str}" if hex_str[0, 2] != "0x" || hex_str[0, 2] != "0X"
618
+ expected_length = bits / 4
619
+ extended_hex_str = if hex_str.length < expected_length
620
+ extend_char = hex_str[0] == "f" ? "f" : "0"
621
+ extend_char * (expected_length - hex_str.length) + hex_str
622
+ else
623
+ hex_str
624
+ end
625
+ binary_str = extended_hex_str.to_i(16).to_s(2).rjust(bits, extended_hex_str[0])
626
+ if binary_str[0] == "1" # 负数
627
+ -((binary_str.tr("01", "10").to_i(2) + 1) & ((1 << bits) - 1))
628
+ else # 正数
629
+ binary_str.to_i(2)
630
+ end
631
+ end
632
+ end
633
+ end
634
+ end
635
+ module AbiCoderRb
636
+ VERSION = "0.1.0"
637
+ end
638
+ module AbiCoderRb
639
+ class DecodingError < StandardError; end
640
+ class EncodingError < StandardError; end
641
+ class ValueError < StandardError; end
642
+ class ValueOutOfBounds < ValueError; end
643
+ BYTE_EMPTY = "".b.freeze
644
+ BYTE_ZERO = "\x00".b.freeze
645
+ BYTE_ONE = "\x01".b.freeze ## note: used for encoding bool for now
646
+ BYTE_FF = "\xff".b.freeze
647
+ UINT_MAX = 2**256 - 1 ## same as 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
648
+ UINT_MIN = 0
649
+ INT_MAX = 2**255 - 1 ## same as 57896044618658097711785492504343953926634992332820282019728792003956564819967
650
+ INT_MIN = -2**255 ## same as -57896044618658097711785492504343953926634992332820282019728792003956564819968
651
+ def hex_to_bin(hex) # convert hex(adecimal) string to binary string
652
+ hex = hex[2..] if %w[0x 0X].include?(hex[0, 2]) ## cut-of leading 0x or 0X if present
653
+ hex.scan(/../).map { |x| x.hex.chr }.join
654
+ end
655
+ alias hex hex_to_bin
656
+ def bin_to_hex(bin) # convert binary string to hex string
657
+ bin.each_byte.map { |byte| "%02x" % byte }.join
658
+ end
659
+ def hex?(str)
660
+ str.start_with?("0x") && str.length.even? && str[2..].match?(/\A\b[0-9a-fA-F]+\b\z/)
661
+ end
662
+ attr_accessor :before_encoding_action, :after_decoding_action
663
+ def before_encoding(action)
664
+ self.before_encoding_action = action
665
+ end
666
+ def after_decoding(action)
667
+ self.after_decoding_action = action
668
+ end
669
+ end
data/lib/.DS_Store CHANGED
Binary file
@@ -1,21 +1,21 @@
1
1
  module AbiCoderRb
2
2
  def decode_array(type, data)
3
- l = decode_uint256(data[0, 32])
4
- raise DecodingError, "Too long length: #{l}" if l > 100_000
3
+ size = decode_uint256(data[0, 32])
4
+ raise DecodingError, "Too many elements: #{size}" if size > 100_000
5
5
 
6
6
  subtype = type.subtype
7
7
 
8
8
  if subtype.dynamic?
9
- raise DecodingError, "Not enough data for head" unless data.size >= 32 + 32 * l
9
+ raise DecodingError, "Not enough data for head" unless data.size >= 32 + 32 * size
10
10
 
11
- start_positions = (1..l).map { |i| 32 + decode_uint256(data[32 * i, 32]) }
11
+ start_positions = (1..size).map { |i| 32 + decode_uint256(data[32 * i, 32]) }
12
12
  start_positions.push(data.size)
13
13
 
14
- outputs = (0...l).map { |i| data[start_positions[i]...start_positions[i + 1]] }
14
+ outputs = (0...size).map { |i| data[start_positions[i]...start_positions[i + 1]] }
15
15
 
16
16
  outputs.map { |out| decode_type(subtype, out) }
17
17
  else
18
- (0...l).map { |i| decode_type(subtype, data[(32 + subtype.size * i)..]) }
18
+ (0...size).map { |i| decode_type(subtype, data[(32 + subtype.size * i)..]) }
19
19
  end
20
20
  end
21
21
  end