Decode sequences and arrays

This commit is contained in:
Mark Spanbroek 2021-11-30 16:22:52 +01:00
parent 767c4ab588
commit 0f4c4d1465
4 changed files with 38 additions and 0 deletions

View File

@ -1,6 +1,7 @@
import pkg/stint
import pkg/stew/endians2
import pkg/upraises
import ./encoding
push: {.upraises:[].}
@ -93,6 +94,20 @@ func finish*(decoder: var AbiDecoder) =
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..<len:
result.add(decoder.read(T))
decoder.finishTuple()
func read*[I,T](decoder: var AbiDecoder, _: type array[I,T]): array[I,T] =
const dynamic = AbiEncoder.isDynamic(T)
decoder.startTuple(dynamic)
for i in 0..<result.len:
result[i] = decoder.read(T)
decoder.finishTuple()
func decode*(_: type AbiDecoder, bytes: seq[byte], T: type): T =
var decoder = AbiDecoder.init(bytes)
result = decoder.read(T)

View File

@ -128,3 +128,11 @@ func encode*[T](_: type AbiEncoder, value: T): seq[byte] =
var encoder = AbiEncoder.init()
encoder.write(value)
encoder.finish()
proc isDynamic*(_: type AbiEncoder, T: type): bool {.compileTime.} =
var encoder = AbiEncoder.init()
encoder.encode(T.default)
encoder.stack[^1].dynamic
proc isStatic*(_: type AbiEncoder, T: type): bool {.compileTime.} =
not AbiEncoder.isDynamic(T)

View File

@ -186,3 +186,12 @@ suite "ABI decoding":
decoder.finishTuple()
decoder.finish()
test "decodes sequences":
checkDecode(@[seq[byte].example, seq[byte].example])
test "decodes arrays with static elements":
checkDecode([array[32, byte].example, array[32, byte].example])
test "decodes arrays with dynamic elements":
checkDecode([seq[byte].example, seq[byte].example])

View File

@ -171,5 +171,11 @@ suite "ABI encoding":
test "encodes strings as UTF-8 byte sequence":
check AbiEncoder.encode("hello!☺") == AbiEncoder.encode("hello!☺".toBytes)
test "can determine whether types are dynamic or static":
check static AbiEncoder.isStatic(uint8)
check static AbiEncoder.isDynamic(seq[byte])
check static AbiEncoder.isStatic(array[2, array[2, byte]])
check static AbiEncoder.isDynamic(array[2, seq[byte]])
# https://medium.com/b2expand/abi-encoding-explanation-4f470927092d
# https://docs.soliditylang.org/en/v0.8.1/abi-spec.html#formal-specification-of-the-encoding