oids: switch from PRNG to random module (#16203)

* switch from PRNG to random module
* fix the regression
* comments + tests
* runnableExamples
* make oids better

(cherry picked from commit 89a21e4ec7)
This commit is contained in:
flywind
2021-01-07 02:38:31 -06:00
committed by narimiran
parent 2eb0442a9a
commit 594831620b
2 changed files with 25 additions and 20 deletions

View File

@@ -12,24 +12,24 @@
## produce a globally distributed unique ID. This implementation was extracted
## from the Mongodb interface and it thus binary compatible with a Mongo OID.
##
## This implementation calls ``math.randomize()`` for the first call of
## This implementation calls `initRand()` for the first call of
## ``genOid``.
import hashes, times, endians
import hashes, times, endians, random
type
Oid* = object ## an OID
Oid* = object ## An OID.
time: int32 ##
fuzz: int32 ##
count: int32 ##
proc `==`*(oid1: Oid, oid2: Oid): bool =
## Compare two Mongo Object IDs for equality
## Compares two Mongo Object IDs for equality.
return (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and
(oid1.count == oid2.count)
proc hash*(oid: Oid): Hash =
## Generate hash of Oid for use in hashtables
## Generates hash of Oid for use in hashtables.
var h: Hash = 0
h = h !& hash(oid.time)
h = h !& hash(oid.fuzz)
@@ -44,7 +44,7 @@ proc hexbyte*(hex: char): int =
else: discard
proc parseOid*(str: cstring): Oid =
## parses an OID.
## Parses an OID.
var bytes = cast[cstring](addr(result.time))
var i = 0
while i < 12:
@@ -52,6 +52,7 @@ proc parseOid*(str: cstring): Oid =
inc(i)
proc oidToString*(oid: Oid, str: cstring) =
## Converts an oid to `str` which must have space allocated for 25 elements.
const hex = "0123456789abcdef"
# work around a compiler bug:
var str = str
@@ -66,35 +67,33 @@ proc oidToString*(oid: Oid, str: cstring) =
str[24] = '\0'
proc `$`*(oid: Oid): string =
## Converts an oid to string.
result = newString(24)
oidToString(oid, result)
proc rand(): cint {.importc: "rand", header: "<stdlib.h>", nodecl.}
proc srand(seed: cint) {.importc: "srand", header: "<stdlib.h>", nodecl.}
var t = getTime().toUnix.int32
srand(t)
var
incr: int = rand()
fuzz: int32 = rand()
t = getTime().toUnix.int32
seed = initRand(t)
incr: int = seed.rand(int.high)
let fuzz = cast[int32](seed.rand(high(int)))
proc genOid*(): Oid =
## generates a new OID.
## Generates a new OID.
runnableExamples:
doAssert ($genOid()).len == 24
if false: doAssert $genOid() == "5fc7f546ddbbc84800006aaf"
t = getTime().toUnix.int32
var i = int32(atomicInc(incr))
var i = cast[int32](atomicInc(incr))
bigEndian32(addr result.time, addr(t))
result.fuzz = fuzz
bigEndian32(addr result.count, addr(i))
proc generatedTime*(oid: Oid): Time =
## returns the generated timestamp of the OID.
## Returns the generated timestamp of the OID.
var tmp: int32
var dummy = oid.time
bigEndian32(addr(tmp), addr(dummy))
result = fromUnix(tmp)
when not defined(testing) and isMainModule:
let xo = genOid()
echo xo.generatedTime

6
tests/stdlib/toids.nim Normal file
View File

@@ -0,0 +1,6 @@
import std/oids
block: # genOid
let x = genOid()
doAssert ($x).len == 24