aboutsummaryrefslogtreecommitdiff
path: root/core/encoding/uuid/generation.odin
diff options
context:
space:
mode:
authorFeoramund <161657516+Feoramund@users.noreply.github.com>2024-06-20 22:57:55 -0400
committerFeoramund <161657516+Feoramund@users.noreply.github.com>2024-06-22 18:21:27 -0400
commit4dacddd85e07af165df5093e14f3f1a767cf63d1 (patch)
treef386ad01cb964f967f2dbc43b09b314f80e84f02 /core/encoding/uuid/generation.odin
parent3af9d31bd52c4714beddd2eaf154eadaf81d14b1 (diff)
Add `core:encoding/uuid`
Diffstat (limited to 'core/encoding/uuid/generation.odin')
-rw-r--r--core/encoding/uuid/generation.odin159
1 files changed, 159 insertions, 0 deletions
diff --git a/core/encoding/uuid/generation.odin b/core/encoding/uuid/generation.odin
new file mode 100644
index 000000000..fe05d3ebd
--- /dev/null
+++ b/core/encoding/uuid/generation.odin
@@ -0,0 +1,159 @@
+package uuid
+
+import "core:crypto/legacy/md5"
+import "core:crypto/legacy/sha1"
+import "core:math/rand"
+import "core:mem"
+
+/*
+Generate a version 3 UUID.
+
+This UUID is generated from a name within a namespace.
+MD5 is used to hash the name with the namespace to produce the UUID.
+
+Inputs:
+- namespace: Another `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 used to generate the name on top of the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v3_bytes :: proc(
+ namespace: Identifier,
+ name: []byte,
+) -> (
+ result: Identifier,
+) {
+ namespace := namespace
+
+ ctx: md5.Context
+ md5.init(&ctx)
+ md5.update(&ctx, namespace.bytes[:])
+ md5.update(&ctx, name)
+ md5.final(&ctx, result.bytes[:])
+
+ result.bytes[VERSION_BYTE_INDEX] &= 0x0F
+ result.bytes[VERSION_BYTE_INDEX] |= 0x30
+
+ result.bytes[VARIANT_BYTE_INDEX] &= 0x3F
+ result.bytes[VARIANT_BYTE_INDEX] |= 0x80
+
+ return
+}
+
+/*
+Generate a version 3 UUID.
+
+This UUID is generated from a name within a namespace.
+MD5 is used to hash the name with the namespace to produce the UUID.
+
+Inputs:
+- namespace: Another `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 used to generate the name on top of the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v3_string :: proc(
+ namespace: Identifier,
+ name: string,
+) -> (
+ result: Identifier,
+) {
+ return generate_v3_bytes(namespace, transmute([]byte)name)
+}
+
+generate_v3 :: proc {
+ generate_v3_bytes,
+ generate_v3_string,
+}
+
+/*
+Generate a version 4 UUID.
+
+This UUID will be pseudorandom, save for 6 pre-determined version and variant bits.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v4 :: proc() -> (result: Identifier) {
+ result.integer = transmute(u128be)rand.uint128()
+
+ result.bytes[VERSION_BYTE_INDEX] &= 0x0F
+ result.bytes[VERSION_BYTE_INDEX] |= 0x40
+
+ result.bytes[VARIANT_BYTE_INDEX] &= 0x3F
+ result.bytes[VARIANT_BYTE_INDEX] |= 0x80
+
+ return
+}
+
+/*
+Generate a version 5 UUID.
+
+This UUID is generated from a name within a namespace.
+SHA1 is used to hash the name with the namespace to produce the UUID.
+
+Inputs:
+- namespace: Another `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 used to generate the name on top of the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v5_bytes :: proc(
+ namespace: Identifier,
+ name: []byte,
+) -> (
+ result: Identifier,
+) {
+ namespace := namespace
+ digest: [sha1.DIGEST_SIZE]byte
+
+ ctx: sha1.Context
+ sha1.init(&ctx)
+ sha1.update(&ctx, namespace.bytes[:])
+ sha1.update(&ctx, name)
+ sha1.final(&ctx, digest[:])
+
+ mem.copy_non_overlapping(&result.bytes, &digest, 16)
+
+ result.bytes[VERSION_BYTE_INDEX] &= 0x0F
+ result.bytes[VERSION_BYTE_INDEX] |= 0x50
+
+ result.bytes[VARIANT_BYTE_INDEX] &= 0x3F
+ result.bytes[VARIANT_BYTE_INDEX] |= 0x80
+
+ return
+}
+
+/*
+Generate a version 5 UUID.
+
+This UUID is generated from a name within a namespace.
+SHA1 is used to hash the name with the namespace to produce the UUID.
+
+Inputs:
+- namespace: Another `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 used to generate the name on top of the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v5_string :: proc(
+ namespace: Identifier,
+ name: string,
+) -> (
+ result: Identifier,
+) {
+ return generate_v5_bytes(namespace, transmute([]byte)name)
+}
+
+generate_v5 :: proc {
+ generate_v5_bytes,
+ generate_v5_string,
+}