I'm trying to write a simple guid module based on Boost.UUID. For now, I tried to start with the RNG implementation (version 4), but I'm GUIDs that are mostly zeros no matter what:
import random, strutils
type
GuidVariant* {.pure.} = enum
ncs, rfc4122, microsoft, future
GuidVersion* {.pure.} = enum
unknown = -1
timeBased = 1
dceSecurity = 2
nameBasedMd5 = 3
randomNumberBased = 4
nameBasedSha1 = 5
Guid* = array[0..15, uint8]
proc random*(self: var Guid) =
var
i = 0
rng: int
randomize()
rng = random(high(int))
for it in 0..15:
i.inc()
if i == sizeof(int):
rng = random(high(int))
i = 0
self[it] = uint8((rng shr (i*8)) and 0xFF)
# variant
self[8] = self[8] and 0xBF'u8
self[8] = self[8] or 0x80'u8
# version
self[6] = self[6] and 0x4F'u8
self[6] = self[6] or 0x40'u8
proc `bool`*(self: Guid): bool {.inline.} =
for i in self: result = i != 0
proc variant*(self: Guid): GuidVariant =
var
octet7 = self[8]
if (octet7 and 0x80'u8) == 0'u8: return GuidVariant.ncs
elif (octet7 and 0xC0'u8) == 0x80'u8: return GuidVariant.rfc4122
elif (octet7 and 0xE0'u8) == 0xC0'u8: return GuidVariant.microsoft
else: return GuidVariant.future
proc version*(self: Guid): GuidVersion =
var
octet9 = self[6]
case octet9 and 0xF0'u8
of 0x10'u8: return GuidVersion.timeBased
of 0x20'u8: return GuidVersion.dceSecurity
of 0x30'u8: return GuidVersion.nameBasedMd5
of 0x40'u8: return GuidVersion.randomNumberBased
of 0x50'u8: return GuidVersion.nameBasedSha1
else: return GuidVersion.unknown
proc `==`*(lhs, rhs: Guid): bool {.inline.} =
for i in 0..15: result = lhs[i] == rhs[i]
proc `<`*(lhs, rhs: Guid): bool {.inline.} =
for i in 0..15: result = lhs[i] < rhs[i]
proc `!=`*(lhs, rhs: Guid): bool {.inline.} =
for i in 0..15: result = lhs[i] != rhs[i]
proc `>`*(lhs, rhs: Guid): bool {.inline.} =
for i in 0..15: result = lhs[i] > rhs[i]
proc `<=`*(lhs, rhs: Guid): bool {.inline.} =
for i in 0..15: result = lhs[i] <= rhs[i]
proc `>=`*(lhs, rhs: Guid): bool {.inline.} =
for i in 0..15: result = lhs[i] >= rhs[i]
proc hash*(self: Guid): int {.inline.} =
for i in self:
result = result xor (int(i) + int(0x9E3779B9) + (result shl 6) + (result shr 2))
proc `$`*(self: Guid): string {.inline.} =
result = ""
for i in 0..15:
result = result & int(self[i]).toHex(2)
if (i == 3) or (i == 5) or (i == 7) or (i == 9):
result = result & '-'