mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-30 18:02:02 +00:00
Make UUID Identfier only a distinct byte array
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
package uuid
|
||||
|
||||
// A RFC 4122 Universally Unique Identifier
|
||||
Identifier :: struct #raw_union {
|
||||
integer: u128be,
|
||||
bytes: [16]u8,
|
||||
}
|
||||
Identifier :: distinct [16]u8
|
||||
|
||||
EXPECTED_LENGTH :: 8 + 4 + 4 + 4 + 12 + 4
|
||||
|
||||
@@ -28,32 +25,24 @@ Variant_Type :: enum {
|
||||
|
||||
// Name string is a fully-qualified domain name.
|
||||
Namespace_DNS := Identifier {
|
||||
bytes = {
|
||||
0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
},
|
||||
0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
}
|
||||
|
||||
// Name string is a URL.
|
||||
Namespace_URL := Identifier {
|
||||
bytes = {
|
||||
0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
},
|
||||
0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
}
|
||||
|
||||
// Name string is an ISO OID.
|
||||
Namespace_OID := Identifier {
|
||||
bytes = {
|
||||
0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
},
|
||||
0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
}
|
||||
|
||||
// Name string is an X.500 DN (in DER or a text output format).
|
||||
Namespace_X500 := Identifier {
|
||||
bytes = {
|
||||
0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
},
|
||||
0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
|
||||
}
|
||||
|
||||
@@ -29,15 +29,15 @@ generate_v3_bytes :: proc(
|
||||
|
||||
ctx: md5.Context
|
||||
md5.init(&ctx)
|
||||
md5.update(&ctx, namespace.bytes[:])
|
||||
md5.update(&ctx, namespace[:])
|
||||
md5.update(&ctx, name)
|
||||
md5.final(&ctx, result.bytes[:])
|
||||
md5.final(&ctx, result[:])
|
||||
|
||||
result.bytes[VERSION_BYTE_INDEX] &= 0x0F
|
||||
result.bytes[VERSION_BYTE_INDEX] |= 0x30
|
||||
result[VERSION_BYTE_INDEX] &= 0x0F
|
||||
result[VERSION_BYTE_INDEX] |= 0x30
|
||||
|
||||
result.bytes[VARIANT_BYTE_INDEX] &= 0x3F
|
||||
result.bytes[VARIANT_BYTE_INDEX] |= 0x80
|
||||
result[VARIANT_BYTE_INDEX] &= 0x3F
|
||||
result[VARIANT_BYTE_INDEX] |= 0x80
|
||||
|
||||
return
|
||||
}
|
||||
@@ -79,13 +79,14 @@ Returns:
|
||||
- result: The generated UUID.
|
||||
*/
|
||||
generate_v4 :: proc() -> (result: Identifier) {
|
||||
result.integer = transmute(u128be)rand.uint128()
|
||||
bytes_generated := rand.read(result[:])
|
||||
assert(bytes_generated == 16, "RNG failed to generate 16 bytes for UUID v4.")
|
||||
|
||||
result.bytes[VERSION_BYTE_INDEX] &= 0x0F
|
||||
result.bytes[VERSION_BYTE_INDEX] |= 0x40
|
||||
result[VERSION_BYTE_INDEX] &= 0x0F
|
||||
result[VERSION_BYTE_INDEX] |= 0x40
|
||||
|
||||
result.bytes[VARIANT_BYTE_INDEX] &= 0x3F
|
||||
result.bytes[VARIANT_BYTE_INDEX] |= 0x80
|
||||
result[VARIANT_BYTE_INDEX] &= 0x3F
|
||||
result[VARIANT_BYTE_INDEX] |= 0x80
|
||||
|
||||
return
|
||||
}
|
||||
@@ -115,17 +116,17 @@ generate_v5_bytes :: proc(
|
||||
|
||||
ctx: sha1.Context
|
||||
sha1.init(&ctx)
|
||||
sha1.update(&ctx, namespace.bytes[:])
|
||||
sha1.update(&ctx, namespace[:])
|
||||
sha1.update(&ctx, name)
|
||||
sha1.final(&ctx, digest[:])
|
||||
|
||||
mem.copy_non_overlapping(&result.bytes, &digest, 16)
|
||||
mem.copy_non_overlapping(&result, &digest, 16)
|
||||
|
||||
result.bytes[VERSION_BYTE_INDEX] &= 0x0F
|
||||
result.bytes[VERSION_BYTE_INDEX] |= 0x50
|
||||
result[VERSION_BYTE_INDEX] &= 0x0F
|
||||
result[VERSION_BYTE_INDEX] |= 0x50
|
||||
|
||||
result.bytes[VARIANT_BYTE_INDEX] &= 0x3F
|
||||
result.bytes[VARIANT_BYTE_INDEX] |= 0x80
|
||||
result[VARIANT_BYTE_INDEX] &= 0x3F
|
||||
result[VARIANT_BYTE_INDEX] |= 0x80
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ read :: proc "contextless" (str: string) -> (id: Identifier, error: Read_Error)
|
||||
return {}, .Invalid_Hexadecimal
|
||||
}
|
||||
|
||||
id.bytes[octet_index] = low | high << 4
|
||||
id[octet_index] = low | high << 4
|
||||
octet_index += 1
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ Returns:
|
||||
- number: The version number.
|
||||
*/
|
||||
version :: proc "contextless" (id: Identifier) -> (number: int) #no_bounds_check {
|
||||
return cast(int)(id.bytes[VERSION_BYTE_INDEX] & 0xF0 >> 4)
|
||||
return cast(int)(id[VERSION_BYTE_INDEX] & 0xF0 >> 4)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -83,13 +83,13 @@ Returns:
|
||||
*/
|
||||
variant :: proc "contextless" (id: Identifier) -> (variant: Variant_Type) #no_bounds_check {
|
||||
switch {
|
||||
case id.bytes[VARIANT_BYTE_INDEX] & 0x80 == 0:
|
||||
case id[VARIANT_BYTE_INDEX] & 0x80 == 0:
|
||||
return .Reserved_Apollo_NCS
|
||||
case id.bytes[VARIANT_BYTE_INDEX] & 0xC0 == 0x80:
|
||||
case id[VARIANT_BYTE_INDEX] & 0xC0 == 0x80:
|
||||
return .RFC_4122
|
||||
case id.bytes[VARIANT_BYTE_INDEX] & 0xE0 == 0xC0:
|
||||
case id[VARIANT_BYTE_INDEX] & 0xE0 == 0xC0:
|
||||
return .Reserved_Microsoft_COM
|
||||
case id.bytes[VARIANT_BYTE_INDEX] & 0xF0 == 0xE0:
|
||||
case id[VARIANT_BYTE_INDEX] & 0xF0 == 0xE0:
|
||||
return .Reserved_Future
|
||||
case:
|
||||
return .Unknown
|
||||
|
||||
@@ -21,15 +21,15 @@ write :: proc(w: io.Writer, id: Identifier) #no_bounds_check {
|
||||
io.write_byte(w, strconv.digits[low_nibble])
|
||||
}
|
||||
|
||||
for index in 0 ..< 4 { write_octet(w, id.bytes[index]) }
|
||||
for index in 0 ..< 4 { write_octet(w, id[index]) }
|
||||
io.write_byte(w, '-')
|
||||
for index in 4 ..< 6 { write_octet(w, id.bytes[index]) }
|
||||
for index in 4 ..< 6 { write_octet(w, id[index]) }
|
||||
io.write_byte(w, '-')
|
||||
for index in 6 ..< 8 { write_octet(w, id.bytes[index]) }
|
||||
for index in 6 ..< 8 { write_octet(w, id[index]) }
|
||||
io.write_byte(w, '-')
|
||||
for index in 8 ..< 10 { write_octet(w, id.bytes[index]) }
|
||||
for index in 8 ..< 10 { write_octet(w, id[index]) }
|
||||
io.write_byte(w, '-')
|
||||
for index in 10 ..< 16 { write_octet(w, id.bytes[index]) }
|
||||
for index in 10 ..< 16 { write_octet(w, id[index]) }
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -52,7 +52,7 @@ test_namespaced_uuids :: proc(t: ^testing.T) {
|
||||
test_writing :: proc(t: ^testing.T) {
|
||||
id: uuid.Identifier
|
||||
|
||||
for &b, i in id.bytes {
|
||||
for &b, i in id {
|
||||
b = u8(i)
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ test_reading :: proc(t: ^testing.T) {
|
||||
id, err := uuid.read("00010203-0405-0607-0809-0a0b0c0d0e0f")
|
||||
testing.expect_value(t, err, nil)
|
||||
|
||||
for b, i in id.bytes {
|
||||
for b, i in id {
|
||||
testing.expect_value(t, b, u8(i))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user