Support encoding and decoding of custom types
This commit is contained in:
parent
987d6f4028
commit
f40101100e
17
Readme.md
17
Readme.md
|
@ -19,12 +19,12 @@ Usage
|
||||||
|
|
||||||
```nim
|
```nim
|
||||||
import contractabi
|
import contractabi
|
||||||
import stint
|
|
||||||
|
|
||||||
# encode unsigned integers, booleans, enums
|
# encode unsigned integers, booleans, enums
|
||||||
AbiEncoder.encode(42'u8)
|
AbiEncoder.encode(42'u8)
|
||||||
|
|
||||||
# encode uint256
|
# encode uint256
|
||||||
|
import stint
|
||||||
AbiEncoder.encode(42.u256)
|
AbiEncoder.encode(42.u256)
|
||||||
|
|
||||||
# encode byte arrays and sequences
|
# encode byte arrays and sequences
|
||||||
|
@ -42,6 +42,21 @@ AbiDecoder.decode(bytes, seq[uint8])
|
||||||
|
|
||||||
# decode tuples
|
# decode tuples
|
||||||
AbiDecoder.decode(bytes, (uint32, bool, seq[byte]) )
|
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
|
[1]: https://docs.soliditylang.org/en/latest/abi-spec.html
|
||||||
|
|
|
@ -146,9 +146,6 @@ func decode[T: tuple](decoder: var AbiDecoder, _: typedesc[T]): ?!T =
|
||||||
decoder.finishTuple()
|
decoder.finishTuple()
|
||||||
success tupl
|
success tupl
|
||||||
|
|
||||||
func read*(decoder: var AbiDecoder, T: type): ?!T =
|
|
||||||
decoder.decode(T)
|
|
||||||
|
|
||||||
func finish(decoder: var AbiDecoder): ?!void =
|
func finish(decoder: var AbiDecoder): ?!void =
|
||||||
doAssert decoder.stack.len == 1, "not all tuples were finished"
|
doAssert decoder.stack.len == 1, "not all tuples were finished"
|
||||||
doAssert decoder.last mod 32 == 0, "encoding invariant broken"
|
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)
|
var value = ?decoder.decode(T)
|
||||||
?decoder.finish()
|
?decoder.finish()
|
||||||
success value
|
success value
|
||||||
|
|
||||||
|
func read*(decoder: var AbiDecoder, T: type): ?!T =
|
||||||
|
decoder.decode(T)
|
||||||
|
|
|
@ -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
|
|
@ -1,4 +1,5 @@
|
||||||
import ./contractabi/testEncoding
|
import ./contractabi/testEncoding
|
||||||
import ./contractabi/testDecoding
|
import ./contractabi/testDecoding
|
||||||
|
import ./contractabi/testCustomTypes
|
||||||
|
|
||||||
{.warning[UnusedImport]:off.}
|
{.warning[UnusedImport]:off.}
|
||||||
|
|
Loading…
Reference in New Issue