summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--lib/pure/oids.nim39
-rw-r--r--tests/stdlib/toids.nim11
3 files changed, 26 insertions, 26 deletions
diff --git a/changelog.md b/changelog.md
index d70a4367d..8b9676a3a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -65,6 +65,8 @@
 - `strutils.find` now uses and defaults to `last = -1` for whole string searches,
   making limiting it to just the first char (`last = 0`) valid.
 - `random.rand` now works with `Ordinal`s.
+- `std/oids` now uses `int64` to store time internally (before it was int32), the length of
+  the string form of `Oid` changes from 24 to 32.
 
 [//]: # "Additions:"
 - Added ISO 8601 week date utilities in `times`:
diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim
index 776c046b1..43eadad27 100644
--- a/lib/pure/oids.nim
+++ b/lib/pure/oids.nim
@@ -9,8 +9,7 @@
 
 ## Nim OID support. An OID is a global ID that consists of a timestamp,
 ## a unique counter and a random value. This combination should suffice to
-## produce a globally distributed unique ID. This implementation was extracted
-## from the MongoDB interface and is thus binary compatible with a MongoDB OID.
+## produce a globally distributed unique ID.
 ##
 ## This implementation calls `initRand()` for the first call of
 ## `genOid`.
@@ -20,7 +19,7 @@ from std/private/decode_helpers import handleHexChar
 
 type
   Oid* = object ## An OID.
-    time: int32
+    time: int64
     fuzz: int32
     count: int32
 
@@ -44,37 +43,27 @@ proc parseOid*(str: cstring): Oid =
   ## Parses an OID.
   var bytes = cast[cstring](addr(result.time))
   var i = 0
-  while i < 12:
+  while i < 16:
     bytes[i] = chr((hexbyte(str[2 * i]) shl 4) or hexbyte(str[2 * i + 1]))
     inc(i)
 
-template toStringImpl[T: string | cstring](result: var T, oid: Oid) =
-  ## Stringifies `oid`.
+proc `$`*(oid: Oid): string =
+  ## Converts an OID to a string.
   const hex = "0123456789abcdef"
-  const N = 24
 
-  when T is string:
-    result.setLen N
+  result.setLen 32
 
   var o = oid
   var bytes = cast[cstring](addr(o))
   var i = 0
-  while i < 12:
+  while i < 16:
     let b = bytes[i].ord
     result[2 * i] = hex[(b and 0xF0) shr 4]
     result[2 * i + 1] = hex[b and 0xF]
     inc(i)
-  when T is cstring:
-    result[N] = '\0'
-
-
-proc `$`*(oid: Oid): string =
-  ## Converts an OID to a string.
-  toStringImpl(result, oid)
-
 
 let
-  t = getTime().toUnix.int32
+  t = getTime().toUnix
 
 var
   seed = initRand(t)
@@ -84,24 +73,24 @@ let fuzz = cast[int32](seed.rand(high(int)))
 
 
 template genOid(result: var Oid, incr: var int, fuzz: int32) =
-  var time = getTime().toUnix.int32
+  var time = getTime().toUnix
   var i = cast[int32](atomicInc(incr))
 
-  bigEndian32(addr result.time, addr(time))
+  bigEndian64(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
+    doAssert ($genOid()).len == 32
   runnableExamples("-r:off"):
-    echo $genOid() # for example, "5fc7f546ddbbc84800006aaf"
+    echo $genOid() # for example, "00000000632c452db08c3d19ee9073e5"
   genOid(result, incr, fuzz)
 
 proc generatedTime*(oid: Oid): Time =
   ## Returns the generated timestamp of the OID.
-  var tmp: int32
+  var tmp: int64
   var dummy = oid.time
-  bigEndian32(addr(tmp), addr(dummy))
+  bigEndian64(addr(tmp), addr(dummy))
   result = fromUnix(tmp)
diff --git a/tests/stdlib/toids.nim b/tests/stdlib/toids.nim
index f162dbe57..72900d1ef 100644
--- a/tests/stdlib/toids.nim
+++ b/tests/stdlib/toids.nim
@@ -1,6 +1,15 @@
+discard """
+  matrix: "--mm:refc; --mm:orc"
+"""
+
 import std/oids
 
 
 block: # genOid
   let x = genOid()
-  doAssert ($x).len == 24
+  doAssert ($x).len == 32
+
+block:
+  let x = genOid()
+  let y = parseOid(cstring($x))
+  doAssert x == y