Add API for creating custom version 8 UUIDs

This commit is contained in:
Feoramund
2024-06-22 17:06:32 -04:00
parent e9b882be05
commit 5a75cac5b9
2 changed files with 106 additions and 3 deletions

View File

@@ -0,0 +1,89 @@
package uuid
import "base:runtime"
/*
Stamp a 128-bit integer as being a valid version 8 UUID.
Per the specification, all version 8 UUIDs are either for experimental or
vendor-specific purposes. This procedure allows for converting arbitrary data
into custom UUIDs.
Inputs:
- integer: Any integer type.
Returns:
- result: A valid version 8 UUID.
*/
stamp_v8_int :: proc(#any_int integer: u128) -> (result: Identifier) {
result = transmute(Identifier)cast(u128be)integer
result[VERSION_BYTE_INDEX] &= 0x0F
result[VERSION_BYTE_INDEX] |= 0x80
result[VARIANT_BYTE_INDEX] &= 0x3F
result[VARIANT_BYTE_INDEX] |= 0x80
return
}
/*
Stamp an array of 16 bytes as being a valid version 8 UUID.
Per the specification, all version 8 UUIDs are either for experimental or
vendor-specific purposes. This procedure allows for converting arbitrary data
into custom UUIDs.
Inputs:
- array: An array of 16 bytes.
Returns:
- result: A valid version 8 UUID.
*/
stamp_v8_array :: proc(array: [16]u8) -> (result: Identifier) {
result = transmute(Identifier)array
result[VERSION_BYTE_INDEX] &= 0x0F
result[VERSION_BYTE_INDEX] |= 0x80
result[VARIANT_BYTE_INDEX] &= 0x3F
result[VARIANT_BYTE_INDEX] |= 0x80
return
}
/*
Stamp a slice of bytes as being a valid version 8 UUID.
If the slice is less than 16 bytes long, the data available will be used.
If it is longer than 16 bytes, only the first 16 will be used.
This procedure does not modify the underlying slice.
Per the specification, all version 8 UUIDs are either for experimental or
vendor-specific purposes. This procedure allows for converting arbitrary data
into custom UUIDs.
Inputs:
- slice: A slice of bytes.
Returns:
- result: A valid version 8 UUID.
*/
stamp_v8_slice :: proc(slice: []u8) -> (result: Identifier) {
runtime.mem_copy_non_overlapping(&result, &slice[0], min(16, len(slice)))
result[VERSION_BYTE_INDEX] &= 0x0F
result[VERSION_BYTE_INDEX] |= 0x80
result[VARIANT_BYTE_INDEX] &= 0x3F
result[VARIANT_BYTE_INDEX] |= 0x80
return
}
stamp_v8 :: proc {
stamp_v8_int,
stamp_v8_array,
stamp_v8_slice,
}

View File

@@ -18,7 +18,13 @@ test_version_and_variant :: proc(t: ^testing.T) {
v5 := uuid_legacy.generate_v5(uuid.Namespace_DNS, "")
v6 := uuid.generate_v6()
v7 := uuid.generate_v7()
v8 := uuid.generate_v8_hash(uuid.Namespace_DNS, "", .SHA512)
_v8_array: [16]u8 = 0xff
v8_int := uuid.stamp_v8(max(u128))
v8_array := uuid.stamp_v8(_v8_array)
v8_slice := uuid.stamp_v8(_v8_array[:])
v8_hash := uuid.generate_v8_hash(uuid.Namespace_DNS, "", .SHA512)
testing.expect_value(t, uuid.version(v1), 1)
testing.expect_value(t, uuid.variant(v1), uuid.Variant_Type.RFC_4122)
@@ -32,8 +38,16 @@ test_version_and_variant :: proc(t: ^testing.T) {
testing.expect_value(t, uuid.variant(v6), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v7), 7)
testing.expect_value(t, uuid.variant(v7), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8), 8)
testing.expect_value(t, uuid.variant(v8), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_int), 8)
testing.expect_value(t, uuid.variant(v8_int), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_array), 8)
testing.expect_value(t, uuid.variant(v8_array), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_slice), 8)
testing.expect_value(t, uuid.variant(v8_slice), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_hash), 8)
testing.expect_value(t, uuid.variant(v8_hash), uuid.Variant_Type.RFC_4122)
}
@(test)