diff --git a/contractabi/decoding.nim b/contractabi/decoding.nim index 6e876e0..bc1a234 100644 --- a/contractabi/decoding.nim +++ b/contractabi/decoding.nim @@ -71,6 +71,22 @@ func read(decoder: var AbiDecoder, amount: int, padding=padLeft): ?!seq[byte] = func decode(decoder: var AbiDecoder, T: type UInt): ?!T = success T.fromBytesBE(?decoder.read(sizeof(T))) +template basetype(Range: type range): untyped = + when Range isnot SomeUnsignedInt: {.error: "only uint ranges supported".} + elif sizeof(Range) == sizeof(uint8): uint8 + elif sizeof(Range) == sizeof(uint16): uint16 + elif sizeof(Range) == sizeof(uint32): uint32 + elif sizeof(Range) == sizeof(uint64): uint64 + else: {.error "unsupported range type".} + +func decode(decoder: var AbiDecoder, T: type range): ?!T = + let bytes = ?decoder.read(sizeof(T)) + let value = basetype(T).fromBytesBE(bytes) + if value in T.low..T.high: + success T(value) + else: + failure "value not in range" + func decode(decoder: var AbiDecoder, T: type bool): ?!T = case ?decoder.read(uint8) of 0: success false diff --git a/tests/contractabi/testDecoding.nim b/tests/contractabi/testDecoding.nim index 7384cd1..1ba9dbd 100644 --- a/tests/contractabi/testDecoding.nim +++ b/tests/contractabi/testDecoding.nim @@ -52,7 +52,11 @@ suite "ABI decoding": checkDecode(SomeRange.low) checkDecode(SomeRange.high) - # TODO: failure to decode when value not in range + test "fails to decode when value not in range": + type SomeRange = range[0x0000'u16..0xAAAA'u16] + let encoded = AbiEncoder.encode(0xFFFF'u16) + let decoded = AbiDecoder.decode(encoded, SomeRange) + check decoded.error.msg == "value not in range" test "decodes enums": type SomeEnum = enum