417 lines
11 KiB
Python

class UUIDParseFailureKind:
FORMAT = 2
class UUIDParseNumbers:
NOSPACE = 2
class UUIDParseResult:
def __init__(self):
self.parsedGuid = Guid()
self.kind = None
self.message = None
def setFailure(self, kind, message):
self.kind = kind
self.message = message
class Guid:
__urand = None
def __init__(self):
if Guid.__urand is None:
Guid.__urand = open("/dev/urandom", "rb")
self.__a = 0
self.__b = 0
self.__c = 0
self.__d = 0
self.__e = 0
self.__f = 0
self.__g = 0
self.__h = 0
self.__i = 0
self.__j = 0
self.__k = 0
@staticmethod
def __stringToInt(guidString : str, parsePos : int, requiredLength : int, flags : int, result : int, parseResult):
parseWhat = guidString[parsePos:(parsePos+requiredLength)]
result = int(parseWhat, 16)
parsePos += requiredLength
return (parsePos, result)
@staticmethod
def from_bytes(b : bytes):
guid = Guid()
guid.__a = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]
guid.__b = (b[5] << 8) | b[4]
guid.__c = ((b[7] << 8) | b[6])
guid.__d = b[8]
guid.__e = b[9]
guid.__f = b[10]
guid.__g = b[11]
guid.__h = b[12]
guid.__i = b[13]
guid.__j = b[14]
guid.__k = b[15]
return guid
@staticmethod
def __tryParseGuidWithDashes(guidString : str) -> UUIDParseResult:
result = UUIDParseResult()
print (guidString)
if guidString == "":
return result
guidString = guidString.replace("{", "").replace("}", "").replace("-", "")
import codecs
try:
myBytes = codecs.decode(guidString, 'hex')
except:
return result
guidBytes = [ myBytes[3], myBytes[2], myBytes[1], myBytes[0], myBytes[5], myBytes[4], myBytes[7], myBytes[6], myBytes[8],
myBytes[9], myBytes[10], myBytes[11], myBytes[12], myBytes[13], myBytes[14], myBytes[15] ]
result.parsedGuid = Guid.from_bytes(guidBytes)
return result
"""
startPos = 0
temp = 0
templ = 0
currentPos = 0
result = UUIDParseResult()
hasDashes = True
if (len(guidString) < 1):
print(guidString)
result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[?]")
return result
# check to see that it's the proper length
if guidString[0] == '{':
if len(guidString) != 38 or guidString[37] != '}':
print(guidString)
result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[38]")
return result
startPos = 1
elif guidString[0] == '(':
if len(guidString) != 38 or guidString[37] != ')':
print(guidString)
result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[38]")
return result
startPos = 1
elif len(guidString) != 36:
if len(guidString) != 32:
print(guidString)
result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[36]")
return result
else:
hasDashes = False
if hasDashes:
if (guidString[8 + startPos] != '-' or
guidString[13 + startPos] != '-' or
guidString[18 + startPos] != '-' or
guidString[23 + startPos] != '-'):
result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidDashes")
return result
currentPos = startPos
(parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 8, UUIDParseNumbers.NOSPACE, temp, result)
result.parsedGuid.__a = temp
currentPos = parsePos
if hasDashes:
currentPos = currentPos + 1; # Increment past the '-';
(parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, temp, result)
result.parsedGuid.__b = temp
currentPos = parsePos
if hasDashes:
currentPos = currentPos + 1 # Increment past the '-';
(parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, temp, result)
result.parsedGuid.__c = temp
currentPos = parsePos
if hasDashes:
currentPos = currentPos + 1 # Increment past the '-';
(parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, temp, result)
result.parsedGuid.__d = temp >> 8
result.parsedGuid.__e = temp - (temp >> 8)
currentPos = parsePos
if hasDashes:
currentPos = currentPos + 1 # Increment past the '-';
startPos = currentPos
(parsePos, templ) = Guid.__stringToInt(guidString, currentPos, 8, UUIDParseNumbers.NOSPACE, templ, result)
currentPos = parsePos
(parsePos, temp2) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, templ, result)
# /*
# if ($currentPos - $startPos != 12) {
# $result->setFailure(UUIDParseFailureKind::FORMAT, "Format_GuidInvLen(*)")
# return $result;
# }
# */
result.parsedGuid.__j = temp2 >> 8
result.parsedGuid.__k = temp2 - (temp2 >> 8)
temp = templ
result.parsedGuid.__f = temp >> 24
result.parsedGuid.__g = (temp >> 16) - (temp >> 24)
result.parsedGuid.__h = (temp >> 8) - (temp >> 16)
result.parsedGuid.__i = temp - (temp >> 8)
return result
"""
def parse(value : str):
if value is None:
return None
result = Guid.__tryParseGuidWithDashes(value)
return result.parsedGuid
def __eq__(self, other):
# /*
# if (
# $uuid->clock_seq_hi_and_reserved == self.clock_seq_hi_and_reserved
# && $uuid->node == self.node
# && $uuid->time_hi_and_version == self.time_hi_and_version
# && $uuid->time_low == self.time_low
# && $uuid->time_mid == self.time_mid
# )
# {
# return true;
# }
# */
return (
other.__a == self.__a
and other.__b == self.__b
and other.__c == self.__c
and other.__d == self.__d
and other.__e == self.__e
and other.__f == self.__f
and other.__g == self.__g
and other.__h == self.__h
and other.__i == self.__i
and other.__j == self.__j
and other.__k == self.__k
)
@staticmethod
def __init_bits():
__pr_bits = False
if Guid.__urand is not None:
__pr_bits += Guid.__urand.read(16)
if not self.__pr_bits:
fp = open ( '/dev/urandom', 'rb' )
if fp is not False:
__pr_bits += fp.read(16)
fp.close()
else:
# If /dev/urandom isn't available (eg: in non-unix systems), use mt_rand().
__pr_bits = ""
for cnt in range(0, 16):
__pr_bits += chr ( __mt_rand ( 0, 255 ) )
return __pr_bits
"""
@brief Generates a Universally Unique IDentifier, version 4.
This function generates a truly random UUID. The built in CakePHP String::uuid() function
is not cryptographically secure. You should uses this function instead.
@see http://tools.ietf.org/html/rfc4122#section-4.4
@see http://en.wikipedia.org/wiki/UUID
@return UUID A UUID, made up of 32 hex digits and 4 hyphens.
"""
@staticmethod
def generate():
uuid = Guid()
__pr_bits = Guid.__init_bits()
uuid.__a = (int(pr_bits[3]) << 24) | (int(pr_bits[2]) << 16) | (int(pr_bits[1]) << 8) | pr_bits[0]
uuid.__b = ((int(pr_bits[5]) << 8) | pr_bits[4])
uuid.__c = ((int(pr_bits[7]) << 8) | pr_bits[6])
uuid.__d = pr_bits[8]
uuid.__e = pr_bits[9]
uuid.__f = pr_bits[10]
uuid.__g = pr_bits[11]
uuid.__h = pr_bits[12]
uuid.__i = pr_bits[13]
uuid.__j = pr_bits[14]
uuid.__k = pr_bits[15]
return uuid
@staticmethod
def __hexToChar(a : int) -> str:
a = a & 0xf
v = 0
if a > 9:
v = a - 10 + 0x61
else:
v = a + 0x30
return chr(v)
@staticmethod
def __hexsToChars(a : int, b : int, hex : bool = False):
guidChars = ""
if hex:
guidChars = "0x"
guidChars += Guid.__hexToChar(a >> 4)
guidChars += Guid.__hexToChar(a)
if hex:
guidChars += ",0x"
guidChars += Guid.__hexToChar(b >> 4)
guidChars += Guid.__hexToChar(b)
return guidChars
# public function __toString()
# {
# }
# public function __toStringFormat($includeDashes = true, $prefix = "{", $suffix = "}")
# {
# $guidChars = $prefix;
# $guidChars += Guid.__hexsToChars(self._a >> 24, self._a >> 16)
# $guidChars += Guid.__hexsToChars(self._a >> 8, self._a)
# if ($includeDashes) $guidChars += '-';
# $guidChars += Guid.__hexsToChars(self._b >> 8, self._b)
# if ($includeDashes) $guidChars += '-';
# $guidChars += Guid.__hexsToChars(self._c >> 8, self._c)
# if ($includeDashes) $guidChars += '-';
# $guidChars += Guid.__hexsToChars(self._d, self._e)
# if ($includeDashes) $guidChars += '-';
# $guidChars += Guid.__hexsToChars(self._f, self._g)
# $guidChars += Guid.__hexsToChars(self._h, self._i)
# $guidChars += Guid.__hexsToChars(self._j, self._k)
# $guidChars += $suffix;
# return $guidChars;
# }
def format(input : str):
output = input
output = output[0:8] + "-" + output[8:(8+4)] + "-" + output[12:12+4] + "-" + output[16:16+4] + "-" + output[20:]
return "{" + output + "}"
def strip(self):
guidChars = ""
guidChars += Guid.__hexsToChars(self.__a >> 24, self.__a >> 16)
guidChars += Guid.__hexsToChars(self.__a >> 8, self.__a)
guidChars += Guid.__hexsToChars(self.__b >> 8, self.__b)
guidChars += Guid.__hexsToChars(self.__c >> 8, self.__c)
guidChars += Guid.__hexsToChars(self.__d, self.__e)
guidChars += Guid.__hexsToChars(self.__f, self.__g)
guidChars += Guid.__hexsToChars(self.__h, self.__i)
guidChars += Guid.__hexsToChars(self.__j, self.__k)
return guidChars.lower()
def __str__(self):
# //return self.format(strtoupper( sprintf ( '%08s%04s%04x%04x%012s', self.time_low, self.time_mid, self.time_hi_and_version, self.clock_seq_hi_and_reserved, self.node ) ))
dash = True
guidChars = "{"
guidChars += Guid.__hexsToChars(self.__a >> 24, self.__a >> 16)
guidChars += Guid.__hexsToChars(self.__a >> 8, self.__a)
if (dash):
guidChars += '-'
guidChars += Guid.__hexsToChars(self.__b >> 8, self.__b)
if (dash):
guidChars += '-'
guidChars += Guid.__hexsToChars(self.__c >> 8, self.__c)
if (dash):
guidChars += '-'
guidChars += Guid.__hexsToChars(self.__d, self.__e)
if (dash):
guidChars += '-'
guidChars += Guid.__hexsToChars(self.__f, self.__g)
guidChars += Guid.__hexsToChars(self.__h, self.__i)
guidChars += Guid.__hexsToChars(self.__j, self.__k)
guidChars += "}"
return guidChars.lower()
@staticmethod
def create():
from uuid import uuid4
u = uuid4()
g = Guid.parse(str(u))
return g
def __key(self):
return (self.__a, self.__b, self.__c, self.__d, self.__e, self.__f, self.__g, self.__h, self.__i, self.__j, self.__k)
def __hash__(self):
return hash(self.__key())
def __eq__(self, other):
if isinstance(other, Guid):
return self.__key() == other.__key()
return NotImplemented
def to_bytes(self) -> bytes:
a = self.__a.to_bytes(4, 'little')
b = self.__b.to_bytes(2, 'little')
c = self.__c.to_bytes(2, 'little')
a0 = a[0]
a1 = a[1]
a2 = a[2]
a3 = a[3]
b0 = b[0]
b1 = b[1]
c0 = c[0]
c1 = c[1]
d = self.__d
e = self.__e
f = self.__f
g = self.__g
h = self.__h
i = self.__i
j = self.__j
k = self.__k
sss = [a0, a1, a2, a3, b0, b1, c0, c1, d, e, f, g, h, i, j, k]
return bytes(sss)