abi_coder_rb 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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