|
@@ -1,6 +1,7 @@
|
|
|
package uuid
|
|
|
|
|
|
import "base:runtime"
|
|
|
+import "core:crypto/hash"
|
|
|
import "core:math/rand"
|
|
|
import "core:time"
|
|
|
|
|
@@ -215,3 +216,118 @@ generate_v7 :: proc {
|
|
|
generate_v7_basic,
|
|
|
generate_v7_with_counter,
|
|
|
}
|
|
|
+
|
|
|
+/*
|
|
|
+Generate a version 8 UUID using a specific hashing algorithm.
|
|
|
+
|
|
|
+This UUID is generated by hashing a name with a namespace.
|
|
|
+
|
|
|
+Note that all version 8 UUIDs are for experimental or vendor-specific use
|
|
|
+cases, per the specification. This use case in particular is for offering a
|
|
|
+non-legacy alternative to UUID versions 3 and 5.
|
|
|
+
|
|
|
+Inputs:
|
|
|
+- namespace: An `Identifier` that is used to represent the underlying namespace.
|
|
|
+ This can be any one of the `Namespace_*` values provided in this package.
|
|
|
+- name: The byte slice which will be hashed with the namespace.
|
|
|
+- algorithm: A hashing algorithm from `core:crypto/hash`.
|
|
|
+
|
|
|
+Returns:
|
|
|
+- result: The generated UUID.
|
|
|
+
|
|
|
+Example:
|
|
|
+ import "core:crypto/hash"
|
|
|
+ import "core:encoding/uuid"
|
|
|
+ import "core:fmt"
|
|
|
+
|
|
|
+ main :: proc() {
|
|
|
+ my_uuid := uuid.generate_v8_hash(uuid.Namespace_DNS, "www.odin-lang.org", .SHA256)
|
|
|
+ my_uuid_string := uuid.to_string(my_uuid, context.temp_allocator)
|
|
|
+ fmt.println(my_uuid_string)
|
|
|
+ }
|
|
|
+
|
|
|
+Output:
|
|
|
+
|
|
|
+ 3730f688-4bff-8dce-9cbf-74a3960c5703
|
|
|
+
|
|
|
+*/
|
|
|
+generate_v8_hash_bytes :: proc(
|
|
|
+ namespace: Identifier,
|
|
|
+ name: []byte,
|
|
|
+ algorithm: hash.Algorithm,
|
|
|
+) -> (
|
|
|
+ result: Identifier,
|
|
|
+) {
|
|
|
+ // 128 bytes should be enough for the foreseeable future.
|
|
|
+ digest: [128]byte
|
|
|
+
|
|
|
+ assert(hash.DIGEST_SIZES[algorithm] >= 16, "Per RFC 9562, the hashing algorithm used must generate a digest of 128 bits or larger.")
|
|
|
+ assert(hash.DIGEST_SIZES[algorithm] < len(digest), "Digest size is too small for this algorithm. The buffer must be increased.")
|
|
|
+
|
|
|
+ hash_context: hash.Context
|
|
|
+ hash.init(&hash_context, algorithm)
|
|
|
+
|
|
|
+ mutable_namespace := namespace
|
|
|
+ hash.update(&hash_context, mutable_namespace[:])
|
|
|
+ hash.update(&hash_context, name[:])
|
|
|
+ hash.final(&hash_context, digest[:])
|
|
|
+
|
|
|
+ runtime.mem_copy_non_overlapping(&result, &digest, 16)
|
|
|
+
|
|
|
+ result[VERSION_BYTE_INDEX] &= 0x0F
|
|
|
+ result[VERSION_BYTE_INDEX] |= 0x80
|
|
|
+
|
|
|
+ result[VARIANT_BYTE_INDEX] &= 0x3F
|
|
|
+ result[VARIANT_BYTE_INDEX] |= 0x80
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+Generate a version 8 UUID using a specific hashing algorithm.
|
|
|
+
|
|
|
+This UUID is generated by hashing a name with a namespace.
|
|
|
+
|
|
|
+Note that all version 8 UUIDs are for experimental or vendor-specific use
|
|
|
+cases, per the specification. This use case in particular is for offering a
|
|
|
+non-legacy alternative to UUID versions 3 and 5.
|
|
|
+
|
|
|
+Inputs:
|
|
|
+- namespace: An `Identifier` that is used to represent the underlying namespace.
|
|
|
+ This can be any one of the `Namespace_*` values provided in this package.
|
|
|
+- name: The string which will be hashed with the namespace.
|
|
|
+- algorithm: A hashing algorithm from `core:crypto/hash`.
|
|
|
+
|
|
|
+Returns:
|
|
|
+- result: The generated UUID.
|
|
|
+
|
|
|
+Example:
|
|
|
+ import "core:crypto/hash"
|
|
|
+ import "core:encoding/uuid"
|
|
|
+ import "core:fmt"
|
|
|
+
|
|
|
+ main :: proc() {
|
|
|
+ my_uuid := uuid.generate_v8_hash(uuid.Namespace_DNS, "www.odin-lang.org", .SHA256)
|
|
|
+ my_uuid_string := uuid.to_string(my_uuid, context.temp_allocator)
|
|
|
+ fmt.println(my_uuid_string)
|
|
|
+ }
|
|
|
+
|
|
|
+Output:
|
|
|
+
|
|
|
+ 3730f688-4bff-8dce-9cbf-74a3960c5703
|
|
|
+
|
|
|
+*/
|
|
|
+generate_v8_hash_string :: proc(
|
|
|
+ namespace: Identifier,
|
|
|
+ name: string,
|
|
|
+ algorithm: hash.Algorithm,
|
|
|
+) -> (
|
|
|
+ result: Identifier,
|
|
|
+) {
|
|
|
+ return generate_v8_hash_bytes(namespace, transmute([]byte)name, algorithm)
|
|
|
+}
|
|
|
+
|
|
|
+generate_v8_hash :: proc {
|
|
|
+ generate_v8_hash_bytes,
|
|
|
+ generate_v8_hash_string,
|
|
|
+}
|