From dfcdb6ec2ab6a5fa53b6a99294a84fd122be8f8d Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Sun, 12 Sep 2038 20:51:24 +0800 Subject: [PATCH 1/6] fixes #20285; prevent oid time overflow at year 2038 --- lib/pure/oids.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index 776c046b1556b..0bddf12d1cc7d 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -74,7 +74,7 @@ proc `$`*(oid: Oid): string = let - t = getTime().toUnix.int32 + t = cast[int32](getTime().toUnix) var seed = initRand(t) @@ -84,7 +84,7 @@ 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 = cast[int32](getTime().toUnix) var i = cast[int32](atomicInc(incr)) bigEndian32(addr result.time, addr(time)) From 2293a48e4f9952ee77e3daebe61e20eb6383273a Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Thu, 22 Sep 2022 18:56:57 +0800 Subject: [PATCH 2/6] Revert "fixes #20285; prevent oid time overflow at year 2038" This reverts commit dfcdb6ec2ab6a5fa53b6a99294a84fd122be8f8d. --- lib/pure/oids.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index 0bddf12d1cc7d..776c046b1556b 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -74,7 +74,7 @@ proc `$`*(oid: Oid): string = let - t = cast[int32](getTime().toUnix) + t = getTime().toUnix.int32 var seed = initRand(t) @@ -84,7 +84,7 @@ let fuzz = cast[int32](seed.rand(high(int))) template genOid(result: var Oid, incr: var int, fuzz: int32) = - var time = cast[int32](getTime().toUnix) + var time = getTime().toUnix.int32 var i = cast[int32](atomicInc(incr)) bigEndian32(addr result.time, addr(time)) From 2a550cf2a60caf419fdc99072d13f6624f7126d4 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Thu, 22 Sep 2022 19:21:56 +0800 Subject: [PATCH 3/6] increase time to 64 bits and clean up --- lib/pure/oids.nim | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index 776c046b1556b..bcd8a7fce19e9 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,28 @@ 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 + const N = 32 - when T is string: - result.setLen N + result.setLen N 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 +74,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) From dc7fe0f17f5e42e39e88cfbfae5e56c79d9aa0c3 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Thu, 22 Sep 2022 19:26:01 +0800 Subject: [PATCH 4/6] add testcase --- tests/stdlib/toids.nim | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/stdlib/toids.nim b/tests/stdlib/toids.nim index f162dbe57ccc9..72900d1efb4c9 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 From c1042e3237d202be251fc10e03f6b0d13d82df43 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Thu, 22 Sep 2022 19:28:40 +0800 Subject: [PATCH 5/6] inline consts --- lib/pure/oids.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index bcd8a7fce19e9..43eadad27b257 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -50,9 +50,8 @@ proc parseOid*(str: cstring): Oid = proc `$`*(oid: Oid): string = ## Converts an OID to a string. const hex = "0123456789abcdef" - const N = 32 - result.setLen N + result.setLen 32 var o = oid var bytes = cast[cstring](addr(o)) From 26a657a23eb0d70d4f4bf9f871bcea903be145dd Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Thu, 22 Sep 2022 19:32:01 +0800 Subject: [PATCH 6/6] add a changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 8d574f2b0b67b..e1a90d70b5ed2 100644 --- a/changelog.md +++ b/changelog.md @@ -54,6 +54,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`: