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 & '-'
    

Reply via email to