I've been trying to extend the Schala/nim-modules github repo by adding a
parseGuid() proc to the module which parses a GUID from a string. At first it
seemed successful until I took a closer look:
I fed in the string "65e1d5b2-eb88-4111-b31f-792ea13afbe3" but printing it back
out (via $parseGuid(myGuidStr)) reads 65E1D5B2-B888-4111-311F-792EA13AFBE3. As
you can see, some of bytes don't match.
Here's the entirety of the module with my additions:
import parseutils, random, streams, 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 randomGuid*(): Guid =
randomize()
for i in 0..15: result[i] = uint8(random(255))
# variant
result[8] = result[8] and 0xbf'u8
result[8] = result[8] or 0x80'u8
# version
result[6] = result[6] and 0x4f'u8
result[6] = result[6] or 0x40'u8
proc nilGuid*(): Guid {.inline.} =
zeroMem(addr(result), sizeof(Guid))
proc parseGuid*(s: string, offset = 0): Guid =
var i = 0
var b = 0
for j in countup(offset, offset+35, 2):
if s[j] == '-': continue
discard s.parseHex(b, j, 2)
result[i] = uint8(b and 0xff)
i.inc
proc `variant`*(self: Guid): GuidVariant =
if (self[8] and 0x80'u8) == 0'u8: return GuidVariant.ncs
elif (self[8] and 0xc0'u8) == 0x80'u8: return GuidVariant.rfc4122
elif (self[8] and 0xe0'u8) == 0xc0'u8: return GuidVariant.microsoft
else: return GuidVariant.future
proc `version`*(self: Guid): GuidVersion =
case self[6] 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]
if result == false: break
proc `!=`*(lhs, rhs: Guid): bool {.inline.} =
for i in 0..15:
result = lhs[i] != rhs[i]
if result == false: break
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 & '-'
proc readGuid*(s: Stream): Guid {.inline.} =
discard s.readData(addr(result), 16)
proc write*(s: Stream, g: var Guid) {.inline.} =
s.writeData(addr(g), 16)