diff --git a/contractabi/decoding.nim b/contractabi/decoding.nim index 97e8a65..eac998a 100644 --- a/contractabi/decoding.nim +++ b/contractabi/decoding.nim @@ -1,6 +1,7 @@ import pkg/stint import pkg/stew/endians2 import pkg/stew/byteutils +import pkg/questionable/results import pkg/upraises import ./encoding @@ -20,7 +21,7 @@ type padRight UInt = SomeUnsignedInt | StUint -func read*(decoder: var AbiDecoder, T: type): T +func read*(decoder: var AbiDecoder, T: type): ?!T func init(_: type Tuple, offset: int, dynamic: bool): Tuple = Tuple(start: offset, index: offset, dynamic: dynamic) @@ -41,55 +42,60 @@ func updateLast(decoder: var AbiDecoder, index: int) = if index > decoder.last: decoder.last = index -func advance(decoder: var AbiDecoder, amount: int) = +func advance(decoder: var AbiDecoder, amount: int): ?!void = decoder.index += amount decoder.updateLast(decoder.index) + success() -func read(decoder: var AbiDecoder, amount: int, padding = padLeft): seq[byte] = +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" @@ -97,14 +103,16 @@ func finishTuple(decoder: var AbiDecoder) = if not tupl.dynamic: decoder.index = tupl.index -func decode(decoder: var AbiDecoder, T: type tuple): T = - const dynamic = AbiEncoder.isDynamic(typeof(result)) - decoder.startTuple(dynamic) - for element in result.fields: - element = decoder.read(typeof(element)) +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 = +func read*(decoder: var AbiDecoder, T: type): ?!T = decoder.decode(T) func finish(decoder: var AbiDecoder) = @@ -112,24 +120,29 @@ func finish(decoder: var AbiDecoder) = doAssert decoder.last == decoder.bytes.len, "unread trailing bytes found" doAssert decoder.last mod 32 == 0, "encoding variant broken" -func decode[T](decoder: var AbiDecoder, _: type seq[T]): seq[T] = - let len = decoder.read(uint64) - decoder.startTuple(dynamic=true) +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..