Support encoding and decoding of custom types

This commit is contained in:
Mark Spanbroek 2021-12-01 17:44:14 +01:00
parent 987d6f4028
commit f40101100e
4 changed files with 45 additions and 4 deletions

View File

@ -19,12 +19,12 @@ Usage
```nim
import contractabi
import stint
# encode unsigned integers, booleans, enums
AbiEncoder.encode(42'u8)
# encode uint256
import stint
AbiEncoder.encode(42.u256)
# encode byte arrays and sequences
@ -42,6 +42,21 @@ AbiDecoder.decode(bytes, seq[uint8])
# decode tuples
AbiDecoder.decode(bytes, (uint32, bool, seq[byte]) )
# add support for encoding of custom types
import questionable/results
type CustomType = object
a: uint16
b: string
func encode(encoder: var AbiEncoder, custom: CustomType) =
encoder.write( (custom.a, custom.b) )
func decode(decoder: var AbiDecoder, T: type CustomType): ?!T =
let (a, b) = ?decoder.read( (uint16, string) )
success CustomType(a: a, b: b)
```
[1]: https://docs.soliditylang.org/en/latest/abi-spec.html

View File

@ -146,9 +146,6 @@ func decode[T: tuple](decoder: var AbiDecoder, _: typedesc[T]): ?!T =
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"
@ -183,3 +180,6 @@ func decode*(_: type AbiDecoder, bytes: seq[byte], T: type): ?!T =
var value = ?decoder.decode(T)
?decoder.finish()
success value
func read*(decoder: var AbiDecoder, T: type): ?!T =
decoder.decode(T)

View File

@ -0,0 +1,25 @@
import std/unittest
import pkg/questionable/results
import contractabi
type CustomType = object
a: uint16
b: string
func encode(encoder: var AbiEncoder, custom: CustomType) =
encoder.write( (custom.a, custom.b) )
func decode(decoder: var AbiDecoder, T: type CustomType): ?!T =
let (a, b) = ?decoder.read( (uint16, string) )
success CustomType(a: a, b: b)
suite "custom types":
let custom = CustomType(a: 42, b: "ultimate answer")
test "can be encoded":
check AbiEncoder.encode(custom) == AbiEncoder.encode( (custom.a, custom.b) )
test "can be decoded":
let encoding = AbiEncoder.encode(custom)
check AbiDecoder.decode(encoding, CustomType) == success custom

View File

@ -1,4 +1,5 @@
import ./contractabi/testEncoding
import ./contractabi/testDecoding
import ./contractabi/testCustomTypes
{.warning[UnusedImport]:off.}