From faabd40c30f84c28ed68575b463a510bc1726554 Mon Sep 17 00:00:00 2001 From: jangko Date: Tue, 14 Feb 2023 20:29:30 +0700 Subject: [PATCH 01/12] reduce compiler warnings --- stew/byteutils.nim | 20 +++++++-------- stew/ctops.nim | 8 ++++-- stew/interval_set.nim | 2 +- stew/keyed_queue.nim | 14 ++++++++--- stew/keyed_queue/kq_debug.nim | 7 +++++- stew/results.nim | 2 +- stew/sorted_set.nim | 4 +-- stew/sorted_set/rbtree_verify.nim | 42 ++++++++++++++++++------------- tests/test_ctops.nim | 17 ++++++++----- tests/test_keyed_queue.nim | 13 +++++----- tests/test_results.nim | 6 +++++ 11 files changed, 86 insertions(+), 49 deletions(-) diff --git a/stew/byteutils.nim b/stew/byteutils.nim index 8d14eeb..4aa214a 100644 --- a/stew/byteutils.nim +++ b/stew/byteutils.nim @@ -25,7 +25,7 @@ else: ##################################### Hex utilities ################################################ proc readHexChar*(c: char): byte - {.raises: [ValueError, Defect], noSideEffect, inline.} = + {.raises: [ValueError], noSideEffect, inline.} = ## Converts an hex char to a byte case c of '0'..'9': result = byte(ord(c) - ord('0')) @@ -42,7 +42,7 @@ template skip0xPrefix(hexStr: openArray[char]): int = func hexToByteArrayImpl( hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int): - int {.raises: [ValueError, Defect].} = + int {.raises: [ValueError].} = var sIdx = skip0xPrefix(hexStr) # Fun with closed intervals doAssert fromIdx >= 0 and @@ -65,7 +65,7 @@ func hexToByteArrayImpl( func hexToByteArray*( hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int) - {.raises: [ValueError, Defect].} = + {.raises: [ValueError].} = ## Read hex-encoded data from `hexStr[mapHex(fromIdx..toIdx)]` and store ## corresponding bytes in `output[fromIdx..toIdx]` where `mapHex` takes into ## account stripped characters. @@ -80,7 +80,7 @@ func hexToByteArray*( discard hexToByteArrayImpl(hexStr, output, fromIdx, toIdx) func hexToByteArray*(hexStr: openArray[char], output: var openArray[byte]) - {.raises: [ValueError, Defect].} = + {.raises: [ValueError].} = ## Read hex-encoded data from `hexStr` and store corresponding bytes in ## `output`. ## @@ -92,7 +92,7 @@ func hexToByteArray*(hexStr: openArray[char], output: var openArray[byte]) hexToByteArray(hexStr, output, 0, output.high) func hexToByteArray*[N: static[int]](hexStr: openArray[char]): array[N, byte] - {.raises: [ValueError, Defect], noinit.}= + {.raises: [ValueError], noinit.}= ## Read hex-encoded data from `hexStr` returning an array of N bytes. ## ## * `0x`/`0X` is stripped if present @@ -103,7 +103,7 @@ func hexToByteArray*[N: static[int]](hexStr: openArray[char]): array[N, byte] hexToByteArray(hexStr, result) func hexToByteArray*(hexStr: openArray[char], N: static int): array[N, byte] - {.raises: [ValueError, Defect], noinit.}= + {.raises: [ValueError], noinit.}= ## Read hex-encoded data from `hexStr` returning an array of N bytes. ## ## * `0x`/`0X` is stripped if present @@ -114,7 +114,7 @@ func hexToByteArray*(hexStr: openArray[char], N: static int): array[N, byte] hexToByteArray(hexStr, result) func hexToByteArrayStrict*(hexStr: openArray[char], output: var openArray[byte]) - {.raises: [ValueError, Defect].} = + {.raises: [ValueError].} = ## Read hex-encoded data from `hexStr` and store corresponding bytes in ## `output`. ## @@ -148,7 +148,7 @@ func hexToByteArrayStrict*(hexStr: openArray[char], N: static int): array[N, byt hexToByteArrayStrict(hexStr, result) func fromHex*[N](A: type array[N, byte], hexStr: string): A - {.raises: [ValueError, Defect], noinit, inline.}= + {.raises: [ValueError], noinit, inline.}= ## Read hex-encoded data from `hexStr` returning an array of N bytes. ## ## * `0x`/`0X` is stripped if present @@ -159,7 +159,7 @@ func fromHex*[N](A: type array[N, byte], hexStr: string): A hexToByteArray(hexStr, result) func hexToPaddedByteArray*[N: static[int]](hexStr: string): array[N, byte] - {.raises: [ValueError, Defect].} = + {.raises: [ValueError].} = ## Read a hex string and store it in a byte array `output`. ## The string may be shorter than the byte array. ## No "endianness" reordering is done. @@ -188,7 +188,7 @@ func hexToPaddedByteArray*[N: static[int]](hexStr: string): array[N, byte] bIdx += shift shr 2 func hexToSeqByte*(hexStr: string): seq[byte] - {.raises: [ValueError, Defect].} = + {.raises: [ValueError].} = ## Read an hex string and store it in a sequence of bytes. No "endianness" reordering is done. if (hexStr.len and 1) == 1: raise (ref ValueError)(msg: "hex string must have even length") diff --git a/stew/ctops.nim b/stew/ctops.nim index a0eb2ec..c9bf43b 100644 --- a/stew/ctops.nim +++ b/stew/ctops.nim @@ -19,9 +19,13 @@ elif sizeof(int) == 4: type AnyItem* = byte|char|int8|uint16|int16|uint32|int32|uint|int +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + proc isEqual*[A: AnyItem, B: AnyItem](c: typedesc[CT], a: openArray[A], - b: openArray[B]): bool {. - raises: [Defect] .} = + b: openArray[B]): bool = ## Perform constant time comparison of two arrays ``a`` and ``b``. ## ## Please note that it only makes sense to compare arrays of the same length. diff --git a/stew/interval_set.nim b/stew/interval_set.nim index 93cd301..aeb267f 100644 --- a/stew/interval_set.nim +++ b/stew/interval_set.nim @@ -112,7 +112,7 @@ import "."/[results, sorted_set] when (NimMajor, NimMinor) < (1, 4): - {.push raises: [Defect].} + {.push raises: [Defect, CatchableError].} else: {.push raises: [].} diff --git a/stew/keyed_queue.nim b/stew/keyed_queue.nim index 5cf0224..0fd7617 100644 --- a/stew/keyed_queue.nim +++ b/stew/keyed_queue.nim @@ -325,13 +325,17 @@ proc shift*[K,V](rq: var KeyedQueue[K,V]): Result[KeyedQueuePair[K,V],void] = ## ## Using the notation introduced with `rq.append` and `rq.prepend`, the ## item returned and deleted is the *left-most* item. + type T = KeyedQueuePair[K,V] if 0 < rq.tab.len: noKeyError("shift"): let kvp = KeyedQueuePair[K,V]( key: rq.kFirst, data: rq.tab[rq.kFirst].data) rq.shiftImpl - return ok(KeyedQueuePair[K,V](kvp)) + when kvp is T: + return ok(kvp) + else: + return ok(T(kvp)) err() proc shiftKey*[K,V](rq: var KeyedQueue[K,V]): Result[K,void] = @@ -355,13 +359,17 @@ proc pop*[K,V](rq: var KeyedQueue[K,V]): Result[KeyedQueuePair[K,V],void] = ## ## Using the notation introduced with `rq.append` and `rq.prepend`, the ## item returned and deleted is the *right-most* item. + type T = KeyedQueuePair[K,V] if 0 < rq.tab.len: noKeyError("pop"): let kvp = KeyedQueuePair[K,V]( key: rq.kLast, data: rq.tab[rq.kLast].data) rq.popImpl - return ok(KeyedQueuePair[K,V](kvp)) + when kvp is T: + return ok(kvp) + else: + return ok(T(kvp)) err() proc popKey*[K,V](rq: var KeyedQueue[K,V]): Result[K,void] = @@ -450,7 +458,7 @@ proc eq*[K,V](rq: var KeyedQueue[K,V]; key: K): Result[V,void] = return ok(rq.tab[key].data) proc `[]`*[K,V](rq: var KeyedQueue[K,V]; key: K): V - {.gcsafe,raises: [Defect,KeyError].} = + {.gcsafe,raises: [KeyError].} = ## This function provides a simplified version of the `eq()` function with ## table semantics. Note that this finction throws a `KeyError` exception ## unless the argument `key` exists in the queue. diff --git a/stew/keyed_queue/kq_debug.nim b/stew/keyed_queue/kq_debug.nim index e756efa..b6de15e 100644 --- a/stew/keyed_queue/kq_debug.nim +++ b/stew/keyed_queue/kq_debug.nim @@ -31,6 +31,11 @@ type kQVfyPrvNxtExpected kQVfyFirstExpected +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + # ------------------------------------------------------------------------------ # Public functions, debugging # ------------------------------------------------------------------------------ @@ -50,7 +55,7 @@ proc `$`*[K,V](item: KeyedQueueItem[K,V]): string = "(" & $item.value & ", link[" & $item.prv & "," & $item.kNxt & "])" proc verify*[K,V](rq: var KeyedQueue[K,V]): Result[void,(K,V,KeyedQueueInfo)] - {.gcsafe,raises: [Defect,KeyError].} = + {.gcsafe,raises: [KeyError].} = ## Check for consistency. Returns an error unless the argument ## queue `rq` is consistent. let tabLen = rq.tab.len diff --git a/stew/results.nim b/stew/results.nim index 1e34365..85e08e8 100644 --- a/stew/results.nim +++ b/stew/results.nim @@ -445,7 +445,7 @@ template isOk*(self: Result): bool = self.oResultPrivate template isErr*(self: Result): bool = not self.oResultPrivate when not defined(nimHasEffectsOfs): - template effectsOf(f: untyped) {.pragma.} + template effectsOf(f: untyped) {.pragma, used.} func map*[T0, E, T1]( self: Result[T0, E], f: proc(x: T0): T1): diff --git a/stew/sorted_set.nim b/stew/sorted_set.nim index 88b1906..616bf8e 100644 --- a/stew/sorted_set.nim +++ b/stew/sorted_set.nim @@ -88,7 +88,7 @@ type RbResult[SortedSetItemRef[K,V]] when (NimMajor, NimMinor) < (1, 4): - {.push raises: [Defect].} + {.push raises: [Defect,CatchableError].} else: {.push raises: [].} @@ -301,7 +301,7 @@ proc `$`*[K,V](rc: SortedSetResult[K,V]): string = proc verify*[K,V](sl: var SortedSet[K,V]): Result[void,(SortedSetItemRef[K,V],RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = ## Checks for consistency, may print an error message. Returns `rbOk` if ## the argument list `sl` is consistent. This function traverses all the ## internal data nodes which might be time consuming. So it would not be diff --git a/stew/sorted_set/rbtree_verify.nim b/stew/sorted_set/rbtree_verify.nim index bf596e8..69ca358 100644 --- a/stew/sorted_set/rbtree_verify.nim +++ b/stew/sorted_set/rbtree_verify.nim @@ -18,11 +18,20 @@ type ## for the equivalent of `a < b` proc(a, b: C): bool {.gcsafe.} - RbPrnFn* = ##\ - ## Handle error message - proc(code: RbInfo; ctxInfo: string) - {.gcsafe, raises: [Defect,CatchableError].} +when (NimMajor, NimMinor) < (1, 4): + type + RbPrnFn* = ##\ + ## Handle error message + proc(code: RbInfo; ctxInfo: string) + {.gcsafe, raises: [Defect,CatchableError].} +else: + type + RbPrnFn* = ##\ + ## Handle error message + proc(code: RbInfo; ctxInfo: string) + {.gcsafe, raises: [].} +type RbDdebug[C,K] = object tree: RbTreeRef[C,K] ## tree, not-Nil node: RbNodeRef[C] ## current node @@ -34,7 +43,7 @@ type msg: string ## collect data when (NimMajor, NimMinor) < (1, 4): - {.push raises: [Defect].} + {.push raises: [Defect, CatchableError].} else: {.push raises: [].} @@ -52,8 +61,7 @@ proc pp[C](n: RbNodeRef[C]): string = result &= "~black" proc doError[C,K](d: var RbDdebug[C,K]; t: RbInfo; s: string): - Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + Result[void,(C,RbInfo)] {.gcsafe.} = if not d.pr.isNil: var msg = s & ": <" & d.node.pp & @@ -63,44 +71,44 @@ proc doError[C,K](d: var RbDdebug[C,K]; t: RbInfo; s: string): err((d.node.casket,t)) proc rootIsRed[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyRootIsRed, "Root node is red") proc redNodeRedLinkLeft[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyRedParentRedLeftLink, "Parent node and left link red") proc redNodeRedLinkRight[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyRedParentRedRightLink, "Parent node and right link red") proc redNodeRedLinkBoth[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyRedParentRedBothLinks, "Parent node and both links red") proc linkLeftCompError[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyLeftLinkGtParent, "Left node greater than parent") proc linkRightCompError[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyRightLinkLtParent, "Right node greater than parent") proc linkBothCompError[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyBothLinkCmpParentReversed, "Left node greater than parent greater than right node") proc blackChainLevelError[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = d.doError(rbVfyBlackChainLevelMismatch, "Inconsistent length of black node chains") proc subTreeVerify[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = let node = d.node doAssert not node.isNil @@ -168,7 +176,7 @@ proc subTreeVerify[C,K](d: var RbDdebug[C,K]): Result[void,(C,RbInfo)] proc rbTreeVerify*[C,K](rbt: RbTreeRef[C,K]; lt: RbLtFn[C] = nil; pr: RbPrnFn = nil): Result[void,(C,RbInfo)] - {.gcsafe, raises: [Defect,CatchableError].} = + {.gcsafe.} = ## Verifies the argument tree `rbt` for ## * No consecutively linked red nodes down the tree ## * Link consisteny: value(leftLink) < value(node) < value(rightLink). This diff --git a/tests/test_ctops.nim b/tests/test_ctops.nim index 4efa8b9..1bd402c 100644 --- a/tests/test_ctops.nim +++ b/tests/test_ctops.nim @@ -9,6 +9,11 @@ import unittest2 import ../stew/ctops +when (NimMajor, NimMinor) < (1, 6): + type DefectEx = AssertionError +else: + type DefectEx = AssertionDefect + suite "Constant-time operations test suite": test "isEqual() test": let @@ -97,17 +102,17 @@ suite "Constant-time operations test suite": CT.isEqual(int64Arr, uint64Arr) == true # Empty arrays - expect(AssertionError): + expect(DefectEx): discard CT.isEqual(emptyArray, emptyArray) - expect(AssertionError): + expect(DefectEx): discard CT.isEqual(emptyArray, emptyString) - expect(AssertionError): + expect(DefectEx): discard CT.isEqual(emptyArray, emptySeq) # Arrays, where T is different type size - expect(AssertionError): + expect(DefectEx): discard CT.isEqual(int8Arr, int16Arr) - expect(AssertionError): + expect(DefectEx): discard CT.isEqual(int16Arr, int32Arr) - expect(AssertionError): + expect(DefectEx): discard CT.isEqual(int8Arr, intArr) diff --git a/tests/test_keyed_queue.nim b/tests/test_keyed_queue.nim index bb677fc..3428f7a 100644 --- a/tests/test_keyed_queue.nim +++ b/tests/test_keyed_queue.nim @@ -17,8 +17,6 @@ import ../stew/keyed_queue/kq_debug const - usedStrutils = newSeq[string]().join(" ") - lruCacheLimit = 10 lruCacheModulo = 13 @@ -50,7 +48,7 @@ let proc `$`(rc: KeyedQueuePair[uint,uint]): string = "(" & $rc.key & "," & $rc.data & ")" -proc `$`(rc: Result[KeyedQueuePair[uint,uint],void]): string = +proc `$`(rc: Result[KeyedQueuePair[uint,uint],void]): string {.used.} = result = "<" if rc.isOk: result &= $rc.value.key & "," & $rc.value.data @@ -136,7 +134,7 @@ proc compileGenericFunctions(rq: var KUQueue) = rq[0] = 0 # so `rq[0]` works discard rq[0] - let ignoreValues = ( + let ignoreValues {.used.} = ( (rq.append(0,0), rq.push(0,0), rq.replace(0,0), rq.prepend(0,0), rq.unshift(0,0), @@ -533,10 +531,13 @@ suite "KeyedQueue: Data queue as LRU cache": c1 = keyList.toLruCache sq = toSeq(c1.q.nextPairs).mapIt(it.key.fromKey) s0 = sq - inx = 5 key = sq[5].toKey - sq.delete(5,5) # delete index 5 in sequence + when (NimMajor, NimMinor) >= (1, 6): + sq.delete(5..5) # delete index 5 in sequence + else: + sq.delete(5, 5) # delete index 5 in sequence + noisy.say &"sq: {s0} {sq}" check c1.q.delete(key).value.key == key diff --git a/tests/test_results.nim b/tests/test_results.nim index 7345981..3358751 100644 --- a/tests/test_results.nim +++ b/tests/test_results.nim @@ -88,12 +88,18 @@ block: doAssert c.isErr # De-reference + when (NimMajor, NimMinor) >= (1, 6): + {.warning[BareExcept]:off.} + try: echo rErr[] doAssert false except: discard + when (NimMajor, NimMinor) >= (1, 6): + {.warning[BareExcept]:on.} + # Comparisons doAssert (rOk == rOk) doAssert (rErr == rErr) From 6cc42beac7fb443fe71a8156e2771c754c0bd91e Mon Sep 17 00:00:00 2001 From: jangko Date: Tue, 14 Feb 2023 21:56:10 +0700 Subject: [PATCH 02/12] reenable Defect raises for Nim 1.2 --- stew/byteutils.nim | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/stew/byteutils.nim b/stew/byteutils.nim index 4aa214a..a6418a0 100644 --- a/stew/byteutils.nim +++ b/stew/byteutils.nim @@ -18,14 +18,16 @@ export arrayops.`&`, arrayops.initArrayWith, arrayops.`[]=` when (NimMajor, NimMinor) < (1, 4): {.push raises: [Defect].} + {.pragma: hexRaises, raises: [Defect, ValueError].} else: {.push raises: [].} + {.pragma: hexRaises, raises: [ValueError].} ######################################################################################################## ##################################### Hex utilities ################################################ proc readHexChar*(c: char): byte - {.raises: [ValueError], noSideEffect, inline.} = + {.hexRaises, noSideEffect, inline.} = ## Converts an hex char to a byte case c of '0'..'9': result = byte(ord(c) - ord('0')) @@ -42,7 +44,7 @@ template skip0xPrefix(hexStr: openArray[char]): int = func hexToByteArrayImpl( hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int): - int {.raises: [ValueError].} = + int {.hexRaises.} = var sIdx = skip0xPrefix(hexStr) # Fun with closed intervals doAssert fromIdx >= 0 and @@ -65,7 +67,7 @@ func hexToByteArrayImpl( func hexToByteArray*( hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int) - {.raises: [ValueError].} = + {.hexRaises.} = ## Read hex-encoded data from `hexStr[mapHex(fromIdx..toIdx)]` and store ## corresponding bytes in `output[fromIdx..toIdx]` where `mapHex` takes into ## account stripped characters. @@ -80,7 +82,7 @@ func hexToByteArray*( discard hexToByteArrayImpl(hexStr, output, fromIdx, toIdx) func hexToByteArray*(hexStr: openArray[char], output: var openArray[byte]) - {.raises: [ValueError].} = + {.hexRaises.} = ## Read hex-encoded data from `hexStr` and store corresponding bytes in ## `output`. ## @@ -92,7 +94,7 @@ func hexToByteArray*(hexStr: openArray[char], output: var openArray[byte]) hexToByteArray(hexStr, output, 0, output.high) func hexToByteArray*[N: static[int]](hexStr: openArray[char]): array[N, byte] - {.raises: [ValueError], noinit.}= + {.hexRaises, noinit.}= ## Read hex-encoded data from `hexStr` returning an array of N bytes. ## ## * `0x`/`0X` is stripped if present @@ -103,7 +105,7 @@ func hexToByteArray*[N: static[int]](hexStr: openArray[char]): array[N, byte] hexToByteArray(hexStr, result) func hexToByteArray*(hexStr: openArray[char], N: static int): array[N, byte] - {.raises: [ValueError], noinit.}= + {.hexRaises, noinit.}= ## Read hex-encoded data from `hexStr` returning an array of N bytes. ## ## * `0x`/`0X` is stripped if present @@ -114,7 +116,7 @@ func hexToByteArray*(hexStr: openArray[char], N: static int): array[N, byte] hexToByteArray(hexStr, result) func hexToByteArrayStrict*(hexStr: openArray[char], output: var openArray[byte]) - {.raises: [ValueError].} = + {.hexRaises.} = ## Read hex-encoded data from `hexStr` and store corresponding bytes in ## `output`. ## @@ -126,7 +128,7 @@ func hexToByteArrayStrict*(hexStr: openArray[char], output: var openArray[byte]) raise (ref ValueError)(msg: "hex string too long") func hexToByteArrayStrict*[N: static[int]](hexStr: openArray[char]): array[N, byte] - {.raises: [ValueError, Defect], noinit, inline.}= + {.hexRaises, noinit, inline.}= ## Read hex-encoded data from `hexStr` and store corresponding bytes in ## `output`. ## @@ -137,7 +139,7 @@ func hexToByteArrayStrict*[N: static[int]](hexStr: openArray[char]): array[N, by hexToByteArrayStrict(hexStr, result) func hexToByteArrayStrict*(hexStr: openArray[char], N: static int): array[N, byte] - {.raises: [ValueError, Defect], noinit, inline.}= + {.hexRaises, noinit, inline.}= ## Read hex-encoded data from `hexStr` and store corresponding bytes in ## `output`. ## @@ -148,7 +150,7 @@ func hexToByteArrayStrict*(hexStr: openArray[char], N: static int): array[N, byt hexToByteArrayStrict(hexStr, result) func fromHex*[N](A: type array[N, byte], hexStr: string): A - {.raises: [ValueError], noinit, inline.}= + {.hexRaises, noinit, inline.}= ## Read hex-encoded data from `hexStr` returning an array of N bytes. ## ## * `0x`/`0X` is stripped if present @@ -159,7 +161,7 @@ func fromHex*[N](A: type array[N, byte], hexStr: string): A hexToByteArray(hexStr, result) func hexToPaddedByteArray*[N: static[int]](hexStr: string): array[N, byte] - {.raises: [ValueError].} = + {.hexRaises.} = ## Read a hex string and store it in a byte array `output`. ## The string may be shorter than the byte array. ## No "endianness" reordering is done. @@ -188,7 +190,7 @@ func hexToPaddedByteArray*[N: static[int]](hexStr: string): array[N, byte] bIdx += shift shr 2 func hexToSeqByte*(hexStr: string): seq[byte] - {.raises: [ValueError].} = + {.hexRaises.} = ## Read an hex string and store it in a sequence of bytes. No "endianness" reordering is done. if (hexStr.len and 1) == 1: raise (ref ValueError)(msg: "hex string must have even length") From c52569abd5a7753c1892bf9fc85c71f0c9b6ac45 Mon Sep 17 00:00:00 2001 From: jangko Date: Wed, 15 Feb 2023 16:18:10 +0700 Subject: [PATCH 03/12] add {.used.} to stddefects for nim 1.4 and above --- stew/shims/stddefects.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stew/shims/stddefects.nim b/stew/shims/stddefects.nim index 91f990e..46a3440 100644 --- a/stew/shims/stddefects.nim +++ b/stew/shims/stddefects.nim @@ -21,3 +21,5 @@ when (NimMajor, NimMinor) < (1, 4): RangeDefect* = RangeError ReraiseDefect* = ReraiseError StackOverflowDefect* = StackOverflowError +else: + {.used.} From e18f5a62af2ade7a1fd1d39635d4e04d944def08 Mon Sep 17 00:00:00 2001 From: c-blake Date: Tue, 21 Feb 2023 16:29:07 -0500 Subject: [PATCH 04/12] Add API call from a (slight) future 1.6 branch with when guards to (#173) * Add API call from a (slight) future 1.6 branch with when guards to deactivate as per claim here https://github.com/status-im/nim-codex/pull/346#issuecomment-1432073926 that this (or something very near it) is where it belongs. * I also cannot find any `shims/parse` import. See discussion here: https://github.com/status-im/nim-stew/pull/173 So, rename module to match upstream Nim stdlib. If anyone complains, re-create `parse.nim` that simply does import & re-export parseutils & self-deprecates. --- stew/shims/parse.nim | 55 ----------------- stew/shims/parseutils.nim | 127 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 55 deletions(-) delete mode 100644 stew/shims/parse.nim create mode 100644 stew/shims/parseutils.nim diff --git a/stew/shims/parse.nim b/stew/shims/parse.nim deleted file mode 100644 index 03e41ad..0000000 --- a/stew/shims/parse.nim +++ /dev/null @@ -1,55 +0,0 @@ -# From: https://github.com/nim-lang/Nim/pull/11067/ -proc parseHex*[T: SomeInteger](s: string, number: var T, start = 0, maxLen = 0): int - {.inline, noSideEffect.} = - ## Parses a hexadecimal number and stores its value in ``number``. - ## - ## Returns the number of the parsed characters or 0 in case of an error. - ## If error, the value of ``number`` is not changed. - ## - ## If ``maxLen == 0``, the parsing continues until the first non-hex character - ## or to the end of the string. Otherwise, no more than ``maxLen`` characters - ## are parsed starting from the ``start`` position. - ## - ## It does not check for overflow. If the value represented by the string is - ## too big to fit into ``number``, only the value of last fitting characters - ## will be stored in ``number`` without producing an error. - runnableExamples: - var num: int - doAssert parseHex("4E_69_ED", num) == 8 - doAssert num == 5138925 - doAssert parseHex("X", num) == 0 - doAssert parseHex("#ABC", num) == 4 - var num8: int8 - doAssert parseHex("0x_4E_69_ED", num8) == 11 - doAssert num8 == 0xED'i8 - doAssert parseHex("0x_4E_69_ED", num8, 3, 2) == 2 - doAssert num8 == 0x4E'i8 - var num8u: uint8 - doAssert parseHex("0x_4E_69_ED", num8u) == 11 - doAssert num8u == 237 - var num64: int64 - doAssert parseHex("4E69ED4E69ED", num64) == 12 - doAssert num64 == 86216859871725 - var i = start - var output = T(0) - var foundDigit = false - let last = min(s.len, if maxLen == 0: s.len else: i + maxLen) - if i + 1 < last and s[i] == '0' and (s[i+1] in {'x', 'X'}): inc(i, 2) - elif i < last and s[i] == '#': inc(i) - while i < last: - case s[i] - of '_': discard - of '0'..'9': - output = output shl 4 or T(ord(s[i]) - ord('0')) - foundDigit = true - of 'a'..'f': - output = output shl 4 or T(ord(s[i]) - ord('a') + 10) - foundDigit = true - of 'A'..'F': - output = output shl 4 or T(ord(s[i]) - ord('A') + 10) - foundDigit = true - else: break - inc(i) - if foundDigit: - number = output - result = i - start diff --git a/stew/shims/parseutils.nim b/stew/shims/parseutils.nim new file mode 100644 index 0000000..3236708 --- /dev/null +++ b/stew/shims/parseutils.nim @@ -0,0 +1,127 @@ +# From: https://github.com/nim-lang/Nim/pull/11067/ +proc parseHex*[T: SomeInteger](s: string, number: var T, start = 0, maxLen = 0): int + {.inline, noSideEffect.} = + ## Parses a hexadecimal number and stores its value in ``number``. + ## + ## Returns the number of the parsed characters or 0 in case of an error. + ## If error, the value of ``number`` is not changed. + ## + ## If ``maxLen == 0``, the parsing continues until the first non-hex character + ## or to the end of the string. Otherwise, no more than ``maxLen`` characters + ## are parsed starting from the ``start`` position. + ## + ## It does not check for overflow. If the value represented by the string is + ## too big to fit into ``number``, only the value of last fitting characters + ## will be stored in ``number`` without producing an error. + runnableExamples: + var num: int + doAssert parseHex("4E_69_ED", num) == 8 + doAssert num == 5138925 + doAssert parseHex("X", num) == 0 + doAssert parseHex("#ABC", num) == 4 + var num8: int8 + doAssert parseHex("0x_4E_69_ED", num8) == 11 + doAssert num8 == 0xED'i8 + doAssert parseHex("0x_4E_69_ED", num8, 3, 2) == 2 + doAssert num8 == 0x4E'i8 + var num8u: uint8 + doAssert parseHex("0x_4E_69_ED", num8u) == 11 + doAssert num8u == 237 + var num64: int64 + doAssert parseHex("4E69ED4E69ED", num64) == 12 + doAssert num64 == 86216859871725 + var i = start + var output = T(0) + var foundDigit = false + let last = min(s.len, if maxLen == 0: s.len else: i + maxLen) + if i + 1 < last and s[i] == '0' and (s[i+1] in {'x', 'X'}): inc(i, 2) + elif i < last and s[i] == '#': inc(i) + while i < last: + case s[i] + of '_': discard + of '0'..'9': + output = output shl 4 or T(ord(s[i]) - ord('0')) + foundDigit = true + of 'a'..'f': + output = output shl 4 or T(ord(s[i]) - ord('a') + 10) + foundDigit = true + of 'A'..'F': + output = output shl 4 or T(ord(s[i]) - ord('A') + 10) + foundDigit = true + else: break + inc(i) + if foundDigit: + number = output + result = i - start + +import std/parseutils; export parseutils +#From https://github.com/nim-lang/Nim/pull/21349 in -devel and in version-1-6: +# https://github.com/nim-lang/Nim/commit/c546ba5d23bb2e7bc562a071c88efd94cca7b89e +# https://github.com/nim-lang/Nim/commit/fca6a0bd6a6d3b9a25d1272e29bc39e88853188e +when not declared(parseSize): # Odd code formatting to minimize diff v. mainLine + const Whitespace = {' ', '\t', '\v', '\r', '\l', '\f'} + + func toLowerAscii(c: char): char = + if c in {'A'..'Z'}: char(uint8(c) xor 0b0010_0000'u8) else: c + + func parseSize*(s: string, size: var int64, alwaysBin=false): int = + ## Parse a size qualified by binary or metric units into `size`. This format + ## is often called "human readable". Result is the number of processed chars + ## or 0 on parse errors and size is rounded to the nearest integer. Trailing + ## garbage like "/s" in "1k/s" is allowed and detected by `result < s.len`. + ## + ## To simplify use, following non-rare wild conventions, and since fractional + ## data like milli-bytes is so rare, unit matching is case-insensitive but for + ## the 'i' distinguishing binary-metric from metric (which cannot be 'I'). + ## + ## An optional trailing 'B|b' is ignored but processed. I.e., you must still + ## know if units are bytes | bits or infer this fact via the case of s[^1] (if + ## users can even be relied upon to use 'B' for byte and 'b' for bit or have + ## that be s[^1]). + ## + ## If `alwaysBin==true` then scales are always binary-metric, but e.g. "KiB" + ## is still accepted for clarity. If the value would exceed the range of + ## `int64`, `size` saturates to `int64.high`. Supported metric prefix chars + ## include k, m, g, t, p, e, z, y (but z & y saturate unless the number is a + ## small fraction). + ## + ## **See also:** + ## * https://en.wikipedia.org/wiki/Binary_prefix + ## * `formatSize module`_ for formatting + runnableExamples: + var res: int64 # caller must still know if 'b' refers to bytes|bits + doAssert parseSize("10.5 MB", res) == 7 + doAssert res == 10_500_000 # decimal metric Mega prefix + doAssert parseSize("64 mib", res) == 6 + doAssert res == 67108864 # 64 shl 20 + doAssert parseSize("1G/h", res, true) == 2 # '/' stops parse + doAssert res == 1073741824 # 1 shl 30, forced binary metric + const prefix = "b" & "kmgtpezy" # byte|bit & lowCase metric-ish prefixes + const scaleM = [1.0, 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24] # 10^(3*idx) + const scaleB = [1.0, 1024, 1048576, 1073741824, 1099511627776.0, # 2^(10*idx) + 1125899906842624.0, 1152921504606846976.0, # ldexp? + 1.180591620717411303424e21, 1.208925819614629174706176e24] + var number: float + var scale = 1.0 + result = parseFloat(s, number) + if number < 0: # While parseFloat accepts negatives .. + result = 0 #.. we do not since sizes cannot be < 0 + if result > 0: + let start = result # Save spot to maybe unwind white to EOS + while result < s.len and s[result] in Whitespace: + inc result + if result < s.len: # Illegal starting char => unity + if (let si = prefix.find(s[result].toLowerAscii); si >= 0): + inc result # Now parse the scale + scale = if alwaysBin: scaleB[si] else: scaleM[si] + if result < s.len and s[result] == 'i': + scale = scaleB[si] # Switch from default to binary-metric + inc result + if result < s.len and s[result].toLowerAscii == 'b': + inc result # Skip optional '[bB]' + else: # Unwind result advancement when there.. + result = start #..is no unit to the end of `s`. + var sizeF = number * scale + 0.5 # Saturate to int64.high when too big + size = if sizeF > 9223372036854774784.0: int64.high else: sizeF.int64 +# Above constant=2^63-1024 avoids C UB; github.com/nim-lang/Nim/issues/20102 or +# stackoverflow.com/questions/20923556/math-pow2-63-1-math-pow2-63-512-is-true From 763d54c1ba2c1f9cdb3b936803a7d0d442064352 Mon Sep 17 00:00:00 2001 From: tersec Date: Fri, 7 Apr 2023 15:12:07 +0000 Subject: [PATCH 05/12] use Nim 2.0 in CI (#175) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b29024b..8fbbd2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: cpu: amd64 #- os: windows #cpu: i386 - branch: [version-1-2, version-1-4, version-1-6, devel] + branch: [version-1-2, version-1-4, version-1-6, version-2-0, devel] include: - target: os: linux From 09c6bc676f4ff59d2f9084c881710b4511009c03 Mon Sep 17 00:00:00 2001 From: tersec Date: Fri, 14 Apr 2023 01:32:27 +0000 Subject: [PATCH 06/12] test both refc and ORC in post-1.6 Nim versions (#180) --- stew.nimble | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/stew.nimble b/stew.nimble index 72761e1..eb6feeb 100644 --- a/stew.nimble +++ b/stew.nimble @@ -30,7 +30,9 @@ proc run(args, path: string) = task test, "Run all tests": build "", "tests/test_helper" for args in [ - "--threads:off", - "--threads:on -d:nimTypeNames", - "--threads:on -d:noIntrinsicsBitOpts -d:noIntrinsicsEndians" - ]: run args, "tests/all_tests" + "--threads:off", + "--threads:on -d:nimTypeNames", + "--threads:on -d:noIntrinsicsBitOpts -d:noIntrinsicsEndians"]: + run args, "tests/all_tests" + if (NimMajor, NimMinor) > (1, 6): + run args & " --mm:refc", "tests/all_tests" From 67fdc87e2521f7e021fd521c41d3228810a183d0 Mon Sep 17 00:00:00 2001 From: jangko Date: Fri, 14 Apr 2023 21:51:50 +0700 Subject: [PATCH 07/12] remove travis and appveyor badge from readme.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 4350129..cff198d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ # stew - status e-something w-something -[![Build Status (Travis)](https://img.shields.io/travis/status-im/nim-stew/master.svg?label=Linux%20/%20macOS "Linux/macOS build status (Travis)")](https://travis-ci.org/status-im/nim-stew) -[![Windows build status (Appveyor)](https://img.shields.io/appveyor/ci/nimbus/nim-stew/master.svg?label=Windows "Windows build status (Appveyor)")](https://ci.appveyor.com/project/nimbus/nim-stew) [![License: Apache](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) ![Stability: experimental](https://img.shields.io/badge/stability-experimental-orange.svg) -![Github action](https://github.com/status-im/nim-stew/workflows/nim-stew%20CI/badge.svg) +![Github action](https://github.com/status-im/nim-stew/workflows/CI/badge.svg) `stew` is collection of utilities, std library extensions and budding libraries that are frequently used at Status, but are too small to deserve their own From 9b985e8ea82d0664295359d8621ad880f6f6073c Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Thu, 20 Apr 2023 13:08:54 +0200 Subject: [PATCH 08/12] results: Add `isOkOr`, `isErrOr` (#176) These two helpers complete `valueOr` and `errorOr` to cover `void` cases where no value should be returned or `Result[void, E]` / `Result[T, void]` is being used - they can be used for a convient early-return style in side-effectful proc:s: ```nim v.update().isOkOr: echo "update failed: ", error ``` --- stew/results.nim | 66 ++++++++++++++++++++++++++++++++++++++++-- tests/test_results.nim | 9 ++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/stew/results.nim b/stew/results.nim index 85e08e8..e6af21e 100644 --- a/stew/results.nim +++ b/stew/results.nim @@ -849,11 +849,67 @@ template unsafeError*[T](self: Result[T, void]) = template value*[T, E](self: Result[T, E]): T = self.get() template value*[T: not void, E](self: var Result[T, E]): var T = self.get() +template isOkOr*[T, E](self: Result[T, E], body: untyped) = + ## Evaluate `body` iff result has been assigned an error + ## `body` is evaluated lazily. + ## + ## Example: + ## ``` + ## let + ## v = Result[int, string].err("hello") + ## x = v.isOkOr: echo "not ok" + ## # experimental: direct error access using an unqualified `error` symbol + ## z = v.isOkOr: echo error + ## ``` + ## + ## `error` access: + ## + ## TODO experimental, might change in the future + ## + ## The template contains a shortcut for accessing the error of the result, + ## it can only be used outside of generic code, + ## see https://github.com/status-im/nim-stew/issues/161#issuecomment-1397121386 + + let s = (self) # TODO avoid copy + if not s.oResultPrivate: + when E isnot void: + template error: E {.used, inject.} = s.eResultPrivate + body + +template isErrOr*[T, E](self: Result[T, E], body: untyped) = + ## Evaluate `body` iff result has been assigned a value + ## `body` is evaluated lazily. + ## + ## Example: + ## ``` + ## let + ## v = Result[int, string].err("hello") + ## x = v.isOkOr: echo "not ok" + ## # experimental: direct error access using an unqualified `error` symbol + ## z = v.isOkOr: echo error + ## ``` + ## + ## `value` access: + ## + ## TODO experimental, might change in the future + ## + ## The template contains a shortcut for accessing the value of the result, + ## it can only be used outside of generic code, + ## see https://github.com/status-im/nim-stew/issues/161#issuecomment-1397121386 + + let s = (self) # TODO avoid copy + if s.oResultPrivate: + when T isnot void: + template value: T {.used, inject.} = s.vResultPrivate + body + template valueOr*[T: not void, E](self: Result[T, E], def: untyped): T = ## Fetch value of result if set, or evaluate `def` ## `def` is evaluated lazily, and must be an expression of `T` or exit ## the scope (for example using `return` / `raise`) ## + ## See `isOkOr` for a version that works with `Result[void, E]`. + ## ## Example: ## ``` ## let @@ -869,11 +925,12 @@ template valueOr*[T: not void, E](self: Result[T, E], def: untyped): T = ## TODO experimental, might change in the future ## ## The template contains a shortcut for accessing the error of the result, - ## without specifying the error - it can only be used outside of generic code, + ## it can only be used outside of generic code, ## see https://github.com/status-im/nim-stew/issues/161#issuecomment-1397121386 ## let s = (self) # TODO avoid copy - if s.oResultPrivate: s.vResultPrivate + if s.oResultPrivate: + s.vResultPrivate else: when E isnot void: template error: E {.used, inject.} = s.eResultPrivate @@ -883,8 +940,11 @@ template errorOr*[T, E: not void](self: Result[T, E], def: untyped): E = ## Fetch error of result if not set, or evaluate `def` ## `def` is evaluated lazily, and must be an expression of `T` or exit ## the scope (for example using `return` / `raise`) + ## + ## See `isErrOr` for a version that works with `Result[T, void]`. let s = (self) # TODO avoid copy - if not s.oResultPrivate: s.eResultPrivate + if not s.oResultPrivate: + s.eResultPrivate else: when T isnot void: template value: T {.used, inject.} = s.vResultPrivate diff --git a/tests/test_results.nim b/tests/test_results.nim index 3358751..73203a3 100644 --- a/tests/test_results.nim +++ b/tests/test_results.nim @@ -70,6 +70,15 @@ block: doAssert rOk.get() == rOk.unsafeGet() + rOk.isOkOr: raiseAssert "should not end up in here" + rErr.isErrOr: raiseAssert "should not end up in here" + + rErr.isOkOr: + doAssert error == rErr.error() + + rOk.isErrOr: + doAssert value == rOk.value() + doAssert rOk.valueOr(failFast()) == rOk.value() let rErrV = rErr.valueOr: error.len From 8caa9771995b266e10b2e7c0de6cbfa698902e68 Mon Sep 17 00:00:00 2001 From: diegomrsantos Date: Tue, 25 Apr 2023 18:16:50 +0200 Subject: [PATCH 09/12] remove HoleEnumConv warning (#184) --- stew/objects.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stew/objects.nim b/stew/objects.nim index b75f8d1..0777249 100644 --- a/stew/objects.nim +++ b/stew/objects.nim @@ -104,7 +104,7 @@ func checkedEnumAssign*[E: enum, I: SomeInteger](res: var E, value: I): bool = if value notin E: return false - res = E value + res = cast[E](value) return true func isZeroMemory*[T](x: T): bool = From 111d939940b4fc475069a68c5a745f5b26ca92bd Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Tue, 25 Apr 2023 21:32:22 +0200 Subject: [PATCH 10/12] assign2: guard against self-assignment / overlapping openArray (#182) --- stew/assign2.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stew/assign2.nim b/stew/assign2.nim index cc8ecad..5e34cf9 100644 --- a/stew/assign2.nim +++ b/stew/assign2.nim @@ -15,7 +15,7 @@ func assignImpl[T](tgt: var openArray[T], src: openArray[T]) = mixin assign when supportsCopyMem(T): if tgt.len > 0: - copyMem(addr tgt[0], unsafeAddr src[0], sizeof(tgt[0]) * tgt.len) + moveMem(addr tgt[0], unsafeAddr src[0], sizeof(tgt[0]) * tgt.len) else: for i in 0.. Date: Thu, 11 May 2023 15:34:41 +0200 Subject: [PATCH 11/12] results: Add Opt/Result converters (#177) Add `optError`, `optValue`, to convert back and forth between Opt and Result These conversions end up being more common than others since "trivial" success/fail-style API often use Opt while combining such API into combined operations tends to prefer richer error reporting. --- stew/results.nim | 14 ++++++++++++++ tests/test_results.nim | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/stew/results.nim b/stew/results.nim index e6af21e..f60af4c 100644 --- a/stew/results.nim +++ b/stew/results.nim @@ -845,6 +845,20 @@ template unsafeError*[T](self: Result[T, void]) = ## See also: `unsafeGet` assert not self.oResultPrivate # Emulate field access defect in debug builds +func optValue*[T, E](self: Result[T, E]): Opt[T] = + ## Return the value of a Result as an Opt, or none if Result is an error + if self.oResultPrivate: + Opt.some(self.vResultPrivate) + else: + Opt.none(T) + +func optError*[T, E](self: Result[T, E]): Opt[E] = + ## Return the error of a Result as an Opt, or none if Result is a value + if self.oResultPrivate: + Opt.none(E) + else: + Opt.some(self.eResultPrivate) + # Alternative spellings for get template value*[T, E](self: Result[T, E]): T = self.get() template value*[T: not void, E](self: var Result[T, E]): var T = self.get() diff --git a/tests/test_results.nim b/tests/test_results.nim index 73203a3..ef767c8 100644 --- a/tests/test_results.nim +++ b/tests/test_results.nim @@ -159,6 +159,12 @@ block: # Expectations doAssert rOk.expect("testOk never fails") == 42 + # Conversions to Opt + doAssert rOk.optValue() == Opt.some(rOk.get()) + doAssert rOk.optError().isNone() + doAssert rErr.optValue().isNone() + doAssert rErr.optError() == Opt.some(rErr.error()) + # Question mark operator func testQn(): Result[int, string] = let x = ?works() - ?works() @@ -371,6 +377,10 @@ block: # Result[T, void] aka `Opt` doAssert Opt.some(42).get() == 42 doAssert Opt.none(int).isNone() + # Construct Result from Opt + doAssert oOk.orErr("error").value() == oOk.get() + doAssert oErr.orErr("error").error() == "error" + block: # `cstring` dangling reference protection type CSRes = Result[void, cstring] From 003fe9f0c83c2b0b2ccbd37087e6d1ccd30a3234 Mon Sep 17 00:00:00 2001 From: diegomrsantos Date: Tue, 23 May 2023 11:05:55 +0200 Subject: [PATCH 12/12] remove cast warnings (#186) --- stew/base58.nim | 6 +++--- stew/bitops2.nim | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stew/base58.nim b/stew/base58.nim index ce38904..efbb33e 100644 --- a/stew/base58.nim +++ b/stew/base58.nim @@ -170,13 +170,13 @@ proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openArray[T], result = Base58Status.Incorrect return let ch = alphabet.decode[int8(instr[i])] - if ch == -1: + if ch < 0: outlen = 0 result = Base58Status.Incorrect return - var c = cast[uint32](ch) + var c = uint32(ch) for j in countdown(size - 1, 0): - let t = cast[uint64](buffer[j]) * 58 + c + let t = uint64(buffer[j]) * 58 + c c = cast[uint32]((t and 0x3F_0000_0000'u64) shr 32) buffer[j] = cast[uint32](t and 0xFFFF_FFFF'u32) if c != 0: diff --git a/stew/bitops2.nim b/stew/bitops2.nim index e252362..0b5a351 100644 --- a/stew/bitops2.nim +++ b/stew/bitops2.nim @@ -82,7 +82,7 @@ func log2truncNim(x: uint8|uint16|uint32): int = v = v or v shr 4 v = v or v shr 8 v = v or v shr 16 - cast[int](lookup[uint32(v * 0x07C4ACDD'u32) shr 27]) + int(lookup[uint32(v * 0x07C4ACDD'u32) shr 27]) func log2truncNim(x: uint64): int = ## Quickly find the log base 2 of a 64-bit integer. @@ -169,9 +169,9 @@ when (defined(gcc) or defined(llvm_gcc) or defined(clang)) and useBuiltins: cast[int](builtin_ffs(cast[cint](x.cuint))) func log2truncBuiltin(v: uint8|uint16|uint32): int = - cast[int](31 - cast[cuint](builtin_clz(v.uint32))) + int(31 - cast[cuint](builtin_clz(v.uint32))) func log2truncBuiltin(v: uint64): int = - cast[int](63 - cast[cuint](builtin_clzll(v))) + int(63 - cast[cuint](builtin_clzll(v))) elif defined(vcc) and useBuiltins: const arch64 = sizeof(int) == 8