diff --git a/stint/io.nim b/stint/io.nim index 59408af..1305927 100644 --- a/stint/io.nim +++ b/stint/io.nim @@ -18,7 +18,7 @@ from stew/byteutils import toHex # Helpers # -------------------------------------------------------- -{.push raises: [], inline, gcsafe.} +{.push raises: [], gcsafe.} template leastSignificantWord*(a: SomeBigInteger): Word = mixin limbs @@ -79,7 +79,7 @@ func to*(a: SomeUnsignedInt, T: typedesc[StUint]): T = # Conversions # -------------------------------------------------------- -{.push raises: [], inline, gcsafe.} +{.push raises: [], gcsafe.} func truncate*(num: StUint, T: typedesc[SomeInteger]): T {.inline.}= ## Extract the int, uint, int8-int64 or uint8-uint64 portion of a multi-precision integer. @@ -106,7 +106,7 @@ func truncate*(num: StInt, T: typedesc[SomeInteger]): T {.inline.}= if num.isNegative: when T is SomeUnsignedInt: - doAssert(false, "cannot truncate negative number to unsigned integer") + raise newException(OverflowDefect, "cannot truncate negative number to unsigned integer") elif sizeof(T) <= sizeof(Word): if n.leastSignificantWord() == Word(T.high) + 1: result = low(T) @@ -136,7 +136,8 @@ func stuint*(a: StUint, bits: static[int]): StUint[bits] {.inline.} = func stuint*(a: StInt, bits: static[int]): StUint[bits] {.inline.} = ## signed int to unsigned int conversion ## bigger to smaller bits conversion, the result is truncated - doAssert(a.isPositive, "Cannot convert negative number to unsigned int") + if a.isNegative: + raise newException(OverflowDefect, "Cannot convert negative number to unsigned int") stuint(a.impl, bits) func smallToBig(a: StInt, bits: static[int]): StInt[bits] = @@ -146,7 +147,7 @@ func smallToBig(a: StInt, bits: static[int]): StInt[bits] = else: result.impl = stuint(a.impl, bits) -func stint*(a: StInt, bits: static[int]): StInt[bits] {.inline.} = +func stint*(a: StInt, bits: static[int]): StInt[bits] = ## signed int to signed int conversion ## will raise exception if input does not fit into destination when a.bits < bits: diff --git a/tests/test_conversion.nim b/tests/test_conversion.nim index 69b8cc2..d4d82b4 100644 --- a/tests/test_conversion.nim +++ b/tests/test_conversion.nim @@ -34,14 +34,14 @@ template chkStintToStuint(chk, handleErr: untyped, N, bits: static[int]) = let z = stint(1, N) let v = stint(-1, N) - handleErr AssertionDefect: + handleErr OverflowDefect: discard stuint(w, bits) let xx = stuint(x, bits) let yy = stuint(y, bits) let zz = stuint(z, bits) - handleErr AssertionDefect: + handleErr OverflowDefect: discard stuint(v, bits) when N <= bits: @@ -52,7 +52,7 @@ template chkStintToStuint(chk, handleErr: untyped, N, bits: static[int]) = chk $y == $yy chk $z == $zz -template chkStintToStint(chk: untyped, N, bits: static[int]) = +template chkStintToStint(chk, handleErr: untyped, N, bits: static[int]) = block: # TODO add low value tests if bug #92 fixed let y = stint(0, N) @@ -76,6 +76,24 @@ template chkStintToStint(chk: untyped, N, bits: static[int]) = chk $z == $zz chk $v == $vv + let w = StInt[N].low + + when bits < N: + handleErr RangeDefect: + discard stint(w, bits) + else: + let ww = stint(w, bits) + chk $w == $ww + + let m = stint(int32.low, N) + let n = stint(int64.low, N) + + let mm = stint(m, bits) + let nn = stint(n, bits) + + chk $m == $mm + chk $n == $nn + template chkStuintToStint(chk, handleErr: untyped, N, bits: static[int]) = block: let y = stuint(0, N) @@ -139,25 +157,25 @@ template testConversion(chk, tst, handleErr: untyped) = chkStintToStuint(chk, handleErr, 512, 512) tst "stint to stint": - chkStintToStint(chk, 64, 64) - chkStintToStint(chk, 64, 128) - chkStintToStint(chk, 64, 256) - chkStintToStint(chk, 64, 512) + chkStintToStint(chk, handleErr, 64, 64) + chkStintToStint(chk, handleErr, 64, 128) + chkStintToStint(chk, handleErr, 64, 256) + chkStintToStint(chk, handleErr, 64, 512) - chkStintToStint(chk, 128, 64) - chkStintToStint(chk, 128, 128) - chkStintToStint(chk, 128, 256) - chkStintToStint(chk, 128, 512) + chkStintToStint(chk, handleErr, 128, 64) + chkStintToStint(chk, handleErr, 128, 128) + chkStintToStint(chk, handleErr, 128, 256) + chkStintToStint(chk, handleErr, 128, 512) - chkStintToStint(chk, 256, 64) - chkStintToStint(chk, 256, 128) - chkStintToStint(chk, 256, 256) - chkStintToStint(chk, 256, 512) + chkStintToStint(chk, handleErr, 256, 64) + chkStintToStint(chk, handleErr, 256, 128) + chkStintToStint(chk, handleErr, 256, 256) + chkStintToStint(chk, handleErr, 256, 512) - chkStintToStint(chk, 512, 64) - chkStintToStint(chk, 512, 128) - chkStintToStint(chk, 512, 256) - chkStintToStint(chk, 512, 512) + chkStintToStint(chk, handleErr, 512, 64) + chkStintToStint(chk, handleErr, 512, 128) + chkStintToStint(chk, handleErr, 512, 256) + chkStintToStint(chk, handleErr, 512, 512) tst "stuint to stint": chkStuintToStint(chk, handleErr, 64, 64) diff --git a/tests/test_io.nim b/tests/test_io.nim index 63dc185..8d9f879 100644 --- a/tests/test_io.nim +++ b/tests/test_io.nim @@ -316,140 +316,140 @@ template testIO(chk, tst, handleErr: untyped) = chkTruncateStint(chk, low(int8), int8, 64) chkTruncateStint(chk, high(int8), uint8, 64) chkTruncateStint(chk, high(int8), int8, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint8, "0x80", 64) chkTruncateStint(chk, low(uint8), uint16, 64) chkTruncateStint(chk, low(int8), int16, 64) chkTruncateStint(chk, high(int8), uint16, 64) chkTruncateStint(chk, high(int8), int16, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint16, "0xFF80", 64) chkTruncateStint(chk, low(uint16), uint16, 64) chkTruncateStint(chk, low(int16), int16, 64) chkTruncateStint(chk, high(int16), uint16, 64) chkTruncateStint(chk, high(int16), int16, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int16), uint16, "0x8000", 64) chkTruncateStint(chk, low(uint8), uint32, 64) chkTruncateStint(chk, low(int8), int32, 64) chkTruncateStint(chk, high(int8), uint32, 64) chkTruncateStint(chk, high(int8), int32, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint32, "0xFFFFFF80", 64) chkTruncateStint(chk, low(uint16), uint32, 64) chkTruncateStint(chk, low(int16), int32, 64) chkTruncateStint(chk, high(int16), uint32, 64) chkTruncateStint(chk, high(int16), int32, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int16), uint32, "0xFFFF8000", 64) chkTruncateStint(chk, low(uint32), uint32, 64) chkTruncateStint(chk, low(int32), int32, 64) chkTruncateStint(chk, high(int32), uint32, 64) chkTruncateStint(chk, high(int32), int32, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int32), uint32, "0x80000000", 64) chkTruncateStint(chk, low(uint8), uint64, 64) chkTruncateStint(chk, low(int8), int64, 64) chkTruncateStint(chk, high(int8), uint64, 64) chkTruncateStint(chk, high(int8), int64, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint64, "0xFFFFFFFFFFFFFF80", 64) chkTruncateStint(chk, low(uint16), uint64, 64) chkTruncateStint(chk, low(int16), int64, 64) chkTruncateStint(chk, high(int16), uint64, 64) chkTruncateStint(chk, high(int16), int64, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int16), uint64, "0xFFFFFFFFFFFF8000", 64) chkTruncateStint(chk, low(uint32), uint64, 64) chkTruncateStint(chk, low(int32), int64, 64) chkTruncateStint(chk, high(int32), uint64, 64) chkTruncateStint(chk, high(int32), int64, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int32), uint64, "0xFFFFFFFF80000000", 64) chkTruncateStint(chk, low(uint64), uint64, 64) chkTruncateStint(chk, low(int64), int64, 64) chkTruncateStint(chk, high(int64), uint64, 64) chkTruncateStint(chk, high(int64), int64, 64) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int64), uint64, "0x8000000000000000", 64) chkTruncateStint(chk, low(uint8), uint8, 128) chkTruncateStint(chk, low(int8), int8, 128) chkTruncateStint(chk, high(int8), uint8, 128) chkTruncateStint(chk, high(int8), int8, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint8, "0x80", 128) chkTruncateStint(chk, low(uint8), uint16, 128) chkTruncateStint(chk, low(int8), int16, 128) chkTruncateStint(chk, high(int8), uint16, 128) chkTruncateStint(chk, high(int8), int16, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint16, "0xFF80", 128) chkTruncateStint(chk, low(uint16), uint16, 128) chkTruncateStint(chk, low(int16), int16, 128) chkTruncateStint(chk, high(int16), uint16, 128) chkTruncateStint(chk, high(int16), int16, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int16), uint16, "0x8000", 128) chkTruncateStint(chk, low(uint8), uint32, 128) chkTruncateStint(chk, low(int8), int32, 128) chkTruncateStint(chk, high(int8), uint32, 128) chkTruncateStint(chk, high(int8), int32, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint32, "0xFFFFFF80", 128) chkTruncateStint(chk, low(uint16), uint32, 128) chkTruncateStint(chk, low(int16), int32, 128) chkTruncateStint(chk, high(int16), uint32, 128) chkTruncateStint(chk, high(int16), int32, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int16), uint32, "0xFFFF8000", 128) chkTruncateStint(chk, low(uint32), uint32, 128) chkTruncateStint(chk, low(int32), int32, 128) chkTruncateStint(chk, high(int32), uint32, 128) chkTruncateStint(chk, high(int32), int32, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int32), uint32, "0x80000000", 128) chkTruncateStint(chk, low(uint8), uint64, 128) chkTruncateStint(chk, low(int8), int64, 128) chkTruncateStint(chk, high(int8), uint64, 128) chkTruncateStint(chk, high(int8), int64, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int8), uint64, "0xFFFFFFFFFFFFFF80", 128) chkTruncateStint(chk, low(uint16), uint64, 128) chkTruncateStint(chk, low(int16), int64, 128) chkTruncateStint(chk, high(int16), uint64, 128) chkTruncateStint(chk, high(int16), int64, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int16), uint64, "0xFFFFFFFFFFFF8000", 128) chkTruncateStint(chk, low(uint32), uint64, 128) chkTruncateStint(chk, low(int32), int64, 128) chkTruncateStint(chk, high(int32), uint64, 128) chkTruncateStint(chk, high(int32), int64, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int32), uint64, "0xFFFFFFFF80000000", 128) chkTruncateStint(chk, low(uint64), uint64, 128) chkTruncateStint(chk, low(int64), int64, 128) chkTruncateStint(chk, high(int64), uint64, 128) chkTruncateStint(chk, high(int64), int64, 128) - handleErr AssertionDefect: + handleErr OverflowDefect: chkTruncateStint(chk, low(int64), uint64, "0x8000000000000000", 128) tst "[stuint] parse - toString roundtrip": @@ -943,7 +943,7 @@ proc main() = test "Parsing an unexpected 0x prefix for a decimal string is a CatchableError and not a defect": let s = "0x123456" - expect(AssertionDefect): + expect(OverflowDefect): discard parse(s, StUint[256], 10) suite "Testing conversion functions: Hex, Bytes, Endianness using secp256k1 curve":