import pkg/stint import pkg/upraises import pkg/stew/byteutils export stint push: {.upraises:[].} type AbiEncoder* = object stack: seq[Tuple] Tuple = object bytes: seq[byte] postponed: seq[Split] dynamic: bool Split = object head: Slice[int] tail: seq[byte] func write*[T](encoder: var AbiEncoder, value: T) func encode*[T](_: type AbiEncoder, value: T): seq[byte] func init*(_: type AbiEncoder): AbiEncoder = AbiEncoder(stack: @[Tuple()]) func append(tupl: var Tuple, bytes: openArray[byte]) = tupl.bytes.add(bytes) func postpone(tupl: var Tuple, bytes: seq[byte]) = var split: Split split.head.a = tupl.bytes.len tupl.append(AbiEncoder.encode(0'u64)) split.head.b = tupl.bytes.high split.tail = bytes tupl.postponed.add(split) func finish(tupl: Tuple): seq[byte] = var bytes = tupl.bytes for split in tupl.postponed: let offset = bytes.len bytes[split.head] = AbiEncoder.encode(offset.uint64) bytes.add(split.tail) bytes func append(encoder: var AbiEncoder, bytes: openArray[byte]) = encoder.stack[^1].append(bytes) func postpone(encoder: var AbiEncoder, bytes: seq[byte]) = if encoder.stack.len > 1: encoder.stack[^1].postpone(bytes) else: encoder.stack[0].append(bytes) func setDynamic(encoder: var AbiEncoder) = encoder.stack[^1].dynamic = true func startTuple(encoder: var AbiEncoder) = encoder.stack.add(Tuple()) func encode(encoder: var AbiEncoder, tupl: Tuple) = if tupl.dynamic: encoder.postpone(tupl.finish()) encoder.setDynamic() else: encoder.append(tupl.finish()) func finishTuple(encoder: var AbiEncoder) = encoder.encode(encoder.stack.pop()) func pad(encoder: var AbiEncoder, len: int) = let padlen = (32 - len mod 32) mod 32 for _ in 0..