mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 23:33:28 +00:00
make oids module better (#16704)
* make oids modules better * Update lib/pure/oids.nim * fix
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
let
|
||||
t = getTime().toUnix.int32
|
||||
|
||||
var
|
||||
t = getTime().toUnix.int32
|
||||
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.
|
||||
|
||||
@@ -21,6 +21,13 @@ proc handleHexChar*(c: char, x: var int): bool {.inline.} =
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc handleHexChar*(c: char): int {.inline.} =
|
||||
case c
|
||||
of '0'..'9': result = (ord(c) - ord('0'))
|
||||
of 'a'..'f': result = (ord(c) - ord('a') + 10)
|
||||
of 'A'..'F': result = (ord(c) - ord('A') + 10)
|
||||
else: discard
|
||||
|
||||
proc decodePercent*(s: openArray[char], i: var int): char =
|
||||
## Converts `%xx` hexadecimal to the character with ordinal number `xx`.
|
||||
##
|
||||
|
||||
Reference in New Issue
Block a user