Browse Source

Make UUID `Identfier` only a distinct byte array

Feoramund 1 year ago
parent
commit
6da99b888a

+ 9 - 20
core/encoding/uuid/definitions.odin

@@ -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,
 }

+ 18 - 17
core/encoding/uuid/generation.odin

@@ -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
 }

+ 6 - 6
core/encoding/uuid/reading.odin

@@ -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

+ 5 - 5
core/encoding/uuid/writing.odin

@@ -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]) }
 }
 
 /*

+ 2 - 2
tests/core/encoding/uuid/test_core_uuid.odin

@@ -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))
     }
 }