diff options
author | flywind <43030857+xflywind@users.noreply.github.com> | 2021-01-25 00:39:25 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-25 07:39:25 +0100 |
commit | 8d3e0c7b9bb1289c249b2f009089326794a8a74a (patch) | |
tree | 7ed83f6170f436055abfab3d8b05ce2f56a11418 /lib/pure | |
parent | d99ea0082944918f23534cb291f6e6d18e5224b7 (diff) | |
download | Nim-8d3e0c7b9bb1289c249b2f009089326794a8a74a.tar.gz |
make oids module better (#16704)
* make oids modules better * Update lib/pure/oids.nim * fix
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/oids.nim | 64 |
1 files changed, 38 insertions, 26 deletions
diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index 957a8193a..1373d2da6 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -13,9 +13,10 @@ ## from the Mongodb interface and it thus binary compatible with a Mongo OID. ## ## This implementation calls `initRand()` for the first call of -## ``genOid``. +## `genOid`. -import hashes, times, endians, random +import std/[hashes, times, endians, random] +from std/private/decode_helpers import handleHexChar type Oid* = object ## An OID. @@ -23,9 +24,9 @@ type fuzz: int32 ## count: int32 ## -proc `==`*(oid1: Oid, oid2: Oid): bool = +proc `==`*(oid1: Oid, oid2: Oid): bool {.inline.} = ## Compares two Mongo Object IDs for equality. - return (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and + result = (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and (oid1.count == oid2.count) proc hash*(oid: Oid): Hash = @@ -36,12 +37,8 @@ proc hash*(oid: Oid): Hash = h = h !& hash(oid.count) result = !$h -proc hexbyte*(hex: char): int = - case hex - of '0'..'9': result = (ord(hex) - ord('0')) - of 'a'..'f': result = (ord(hex) - ord('a') + 10) - of 'A'..'F': result = (ord(hex) - ord('A') + 10) - else: discard +proc hexbyte*(hex: char): int {.inline.} = + result = handleHexChar(hex) proc parseOid*(str: cstring): Oid = ## Parses an OID. @@ -51,45 +48,60 @@ proc parseOid*(str: cstring): Oid = bytes[i] = chr((hexbyte(str[2 * i]) shl 4) or hexbyte(str[2 * i + 1])) inc(i) -proc oidToString*(oid: Oid, str: cstring) = - ## Converts an oid to `str` which must have space allocated for 25 elements. +template toStringImpl[T: string | cstring](result: var T, oid: Oid) = + ## Stringifies `oid`. const hex = "0123456789abcdef" - # work around a compiler bug: - var str = str + const N = 24 + + when T is string: + result.setLen N + var o = oid var bytes = cast[cstring](addr(o)) var i = 0 while i < 12: let b = bytes[i].ord - str[2 * i] = hex[(b and 0xF0) shr 4] - str[2 * i + 1] = hex[b and 0xF] + result[2 * i] = hex[(b and 0xF0) shr 4] + result[2 * i + 1] = hex[b and 0xF] inc(i) - str[24] = '\0' + when T is cstring: + result[N] = '\0' + +proc oidToString*(oid: Oid, str: cstring) {.deprecated: "unsafe; use `$`".} = + ## Converts an oid to `str` which must have space allocated for 25 elements. + # work around a compiler bug: + var str = str + toStringImpl(str, oid) proc `$`*(oid: Oid): string = ## Converts an oid to string. - result = newString(24) - oidToString(oid, result) + toStringImpl(result, oid) -var +let t = getTime().toUnix.int32 + +var seed = initRand(t) incr: int = seed.rand(int.high) let fuzz = cast[int32](seed.rand(high(int))) + +template genOid(result: var Oid, incr: var int, fuzz: int32) = + var time = getTime().toUnix.int32 + var i = cast[int32](atomicInc(incr)) + + bigEndian32(addr result.time, addr(time)) + result.fuzz = fuzz + bigEndian32(addr result.count, addr(i)) + proc genOid*(): Oid = ## Generates a new OID. runnableExamples: doAssert ($genOid()).len == 24 if false: doAssert $genOid() == "5fc7f546ddbbc84800006aaf" - t = getTime().toUnix.int32 - var i = cast[int32](atomicInc(incr)) - - bigEndian32(addr result.time, addr(t)) - result.fuzz = fuzz - bigEndian32(addr result.count, addr(i)) + genOid(result, incr, fuzz) proc generatedTime*(oid: Oid): Time = ## Returns the generated timestamp of the OID. |