import pkg/stint import pkg/stew/endians2 import pkg/stew/byteutils import pkg/questionable/results import pkg/upraises import ./encoding push: {.upraises:[].} type AbiDecoder* = object bytes: seq[byte] stack: seq[Tuple] last: int Tuple = object start: int index: int dynamic: bool Padding = enum padLeft, padRight UInt = SomeUnsignedInt | StUint func read*(decoder: var AbiDecoder, T: type): ?!T func init(_: type Tuple, offset: int, dynamic: bool): Tuple = Tuple(start: offset, index: offset, dynamic: dynamic) func init(_: type AbiDecoder, bytes: seq[byte], offset=0): AbiDecoder = AbiDecoder(bytes: bytes, stack: @[Tuple.init(offset, dynamic=false)]) func currentTuple(decoder: var AbiDecoder): var Tuple = decoder.stack[^1] func index(decoder: var AbiDecoder): var int = decoder.currentTuple.index func `index=`(decoder: var AbiDecoder, value: int) = decoder.currentTuple.index = value func updateLast(decoder: var AbiDecoder, index: int) = if index > decoder.last: decoder.last = index func advance(decoder: var AbiDecoder, amount: int): ?!void = decoder.index += amount decoder.updateLast(decoder.index) if decoder.index <= decoder.bytes.len: success() else: failure "reading past end" func skipPadding(decoder: var AbiDecoder, amount: int): ?!void = let index = decoder.index ?decoder.advance(amount) for i in index.. 1, "unable to finish a tuple that hasn't started" let tupl = decoder.stack.pop() if not tupl.dynamic: decoder.index = tupl.index func decode[T: tuple](decoder: var AbiDecoder, _: typedesc[T]): ?!T = const dynamic = AbiEncoder.isDynamic(T) var tupl: T ?decoder.startTuple(dynamic) for element in tupl.fields: element = ?decoder.read(typeof(element)) decoder.finishTuple() success tupl func read*(decoder: var AbiDecoder, T: type): ?!T = decoder.decode(T) func finish(decoder: var AbiDecoder): ?!void = doAssert decoder.stack.len == 1, "not all tuples were finished" doAssert decoder.last mod 32 == 0, "encoding invariant broken" if decoder.last != decoder.bytes.len: failure "unread trailing bytes found" else: success() func decode[T](decoder: var AbiDecoder, _: type seq[T]): ?!seq[T] = var sequence: seq[T] let len = ?decoder.read(uint64) ?decoder.startTuple(dynamic=true) for _ in 0..