Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

oids: switch from PRNG to random module #16203

Merged
merged 10 commits into from
Jan 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions lib/pure/oids.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -44,14 +44,15 @@ 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:
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.
const hex = "0123456789abcdef"
# work around a compiler bug:
var str = str
Expand All @@ -66,35 +67,33 @@ proc oidToString*(oid: Oid, str: cstring) =
str[24] = '\0'

proc `$`*(oid: Oid): string =
## Converts an oid to string.
timotheecour marked this conversation as resolved.
Show resolved Hide resolved
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)
ringabout marked this conversation as resolved.
Show resolved Hide resolved
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.
ringabout marked this conversation as resolved.
Show resolved Hide resolved
runnableExamples:
doAssert ($genOid()).len == 24
if false: doAssert $genOid() == "5fc7f546ddbbc84800006aaf"
t = getTime().toUnix.int32
ringabout marked this conversation as resolved.
Show resolved Hide resolved
var i = int32(atomicInc(incr))
var i = cast[int32](atomicInc(incr))
ringabout marked this conversation as resolved.
Show resolved Hide resolved

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))
ringabout marked this conversation as resolved.
Show resolved Hide resolved
result = fromUnix(tmp)

when not defined(testing) and isMainModule:
let xo = genOid()
echo xo.generatedTime
6 changes: 6 additions & 0 deletions tests/stdlib/toids.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import std/oids


block: # genOid
let x = genOid()
doAssert ($x).len == 24