///|
/// A standard RFC 4122 UUID encoded as BSON Binary subtype 4.
pub struct Uuid {
bytes : Bytes
} derive(Eq, Debug)
///|
pub fn Uuid::from_bytes(bytes : Bytes) -> Uuid raise BsonError {
if bytes.length() != 16 {
raise bson_error(InvalidUuid, -1, "$", "UUID must contain exactly 16 bytes")
}
{ bytes, }
}
///|
pub fn Uuid::from_string(value : String) -> Uuid raise BsonError {
let text = if value.has_prefix("urn:uuid:") {
value[9:].to_owned()
} else {
value
}
let compact = StringBuilder()
for index, code in text.code_units() {
if code == '-' {
if text.length() != 36 || !(index is (8 | 13 | 18 | 23)) {
raise bson_error(InvalidUuid, -1, "$", "invalid UUID hyphen placement")
}
} else if hex_nibble(code) is Some(_) {
compact.write_string(text[index:index + 1].to_owned())
} else {
raise bson_error(InvalidUuid, -1, "$", "invalid hexadecimal UUID digit")
}
}
let hex = compact.to_string()
if hex.length() != 32 {
raise bson_error(
InvalidUuid,
-1,
"$",
"UUID must contain 32 hexadecimal digits",
)
}
let bytes : Array[Byte] = []
for index in 0..<16 {
let high = hex_nibble(hex[index * 2]).unwrap()
let low = hex_nibble(hex[index * 2 + 1]).unwrap()
bytes.push((high * 16 + low).to_byte())
}
{ bytes: Bytes::from_array(bytes) }
}
///|
pub fn Uuid::bytes(self : Uuid) -> Bytes {
self.bytes
}
///|
pub fn Uuid::to_string(self : Uuid) -> String {
let result = StringBuilder()
for index, byte in self.bytes {
if index is (4 | 6 | 8 | 10) {
result.write_string("-")
}
result.write_string(byte.to_hex())
}
result.to_string()
}
///|
pub fn Uuid::to_binary(self : Uuid) -> Binary {
Binary::new(Uuid, self.bytes)
}
///|
pub fn Uuid::from_binary(binary : Binary) -> Uuid raise BsonError {
if binary.subtype() != Uuid {
raise bson_error(InvalidUuid, -1, "$", "UUID requires Binary subtype 4")
}
Uuid::from_bytes(binary.bytes())
}
///|
pub fn Binary::as_uuid(self : Binary) -> Uuid? {
try Uuid::from_binary(self) catch {
_ => None
} noraise {
value => Some(value)
}
}