import pkg/stint import pkg/stew/endians2 import pkg/upraises import ./encoding push: {.upraises:[].} type AbiDecoder* = object bytes: seq[byte] index: int stack: seq[Tuple] Tuple = object start: int finish: int dynamic: bool Padding = enum padLeft, padRight UInt = SomeUnsignedInt | StUint func init*(_: type AbiDecoder, bytes: seq[byte], offset=0): AbiDecoder = AbiDecoder(bytes: bytes, index: offset, stack: @[Tuple()]) func currentTuple(decoder: var AbiDecoder): var Tuple = decoder.stack[^1] func updateFinish(decoder: var AbiDecoder, index: int) = if index > decoder.currentTuple.finish: decoder.currentTuple.finish = index func advance(decoder: var AbiDecoder, amount: int) = decoder.index += amount decoder.updateFinish(decoder.index) func read(decoder: var AbiDecoder, amount: int, padding = padLeft): seq[byte] = let padlen = (32 - amount mod 32) mod 32 if padding == padLeft: decoder.advance(padlen) result = decoder.bytes[decoder.index.. 1, "unable to finish a tuple that hasn't started" let tupl = decoder.stack.pop() decoder.updateFinish(tupl.finish) decoder.index = tupl.finish func finish*(decoder: var AbiDecoder) = doAssert decoder.stack.len == 1, "not all tuples were finished" doAssert decoder.index == decoder.bytes.len, "unread trailing bytes found" doAssert decoder.index mod 32 == 0, "encoding variant broken" func read*[T](decoder: var AbiDecoder, _: type seq[T]): seq[T] = let len = decoder.read(uint64) decoder.startTuple(dynamic=true) for _ in 0..