diff --git a/core/encoding/uuid/definitions.odin b/core/encoding/uuid/definitions.odin index 6810b1cb6..fe13ca99a 100644 --- a/core/encoding/uuid/definitions.odin +++ b/core/encoding/uuid/definitions.odin @@ -18,6 +18,10 @@ VERSION_7_COUNTER_SHIFT :: 64 @(private) NO_CSPRNG_ERROR :: "The context random generator is not cryptographic. See the documentation for an example of how to set one up." +@(private) +BIG_CLOCK_ERROR :: "The clock sequence can only hold 14 bits of data, therefore no number greater than 16,383 (0x3FFF)." +@(private) +VERSION_7_BIG_COUNTER_ERROR :: "This implementation of the version 7 UUID counter can only hold 12 bits of data, therefore no number greater than 4,095 (0xFFF)." Read_Error :: enum { None, diff --git a/core/encoding/uuid/generation.odin b/core/encoding/uuid/generation.odin index bf41b4a8c..427d5243e 100644 --- a/core/encoding/uuid/generation.odin +++ b/core/encoding/uuid/generation.odin @@ -17,7 +17,7 @@ Returns: - result: The generated UUID. */ generate_v1 :: proc(clock_seq: u16, node: Maybe([6]u8) = nil, timestamp: Maybe(time.Time) = nil) -> (result: Identifier) { - assert(clock_seq <= 0x3FFF, "The clock sequence can only hold 14 bits of data; no number greater than 16,383.") + assert(clock_seq <= 0x3FFF, BIG_CLOCK_ERROR) unix_time_in_hns_intervals := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 100 uuid_timestamp := cast(u64le)(HNS_INTERVALS_BETWEEN_GREG_AND_UNIX + unix_time_in_hns_intervals) @@ -89,13 +89,15 @@ Returns: generate_v6 :: proc(clock_seq: Maybe(u16) = nil, node: Maybe([6]u8) = nil, timestamp: Maybe(time.Time) = nil) -> (result: Identifier) { unix_time_in_hns_intervals := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 100 - timestamp := cast(u128be)(HNS_INTERVALS_BETWEEN_GREG_AND_UNIX + unix_time_in_hns_intervals) + uuid_timestamp := cast(u128be)(HNS_INTERVALS_BETWEEN_GREG_AND_UNIX + unix_time_in_hns_intervals) - result |= transmute(Identifier)(timestamp & 0x0FFFFFFF_FFFFF000 << 68) - result |= transmute(Identifier)(timestamp & 0x00000000_00000FFF << 64) + result = transmute(Identifier)( + uuid_timestamp & 0x0FFFFFFF_FFFFF000 << 68 | + uuid_timestamp & 0x00000000_00000FFF << 64 + ) if realized_clock_seq, ok := clock_seq.?; ok { - assert(realized_clock_seq <= 0x3FFF, "The clock sequence can only hold 14 bits of data, therefore no number greater than 16,383.") + assert(realized_clock_seq <= 0x3FFF, BIG_CLOCK_ERROR) result[8] |= cast(u8)(realized_clock_seq & 0x3F00 >> 8) result[9] = cast(u8)realized_clock_seq } else { @@ -126,7 +128,7 @@ generate_v6 :: proc(clock_seq: Maybe(u16) = nil, node: Maybe([6]u8) = nil, times Generate a version 7 UUID. This UUID will be pseudorandom, save for 6 pre-determined version and variant -bits and a 48 bit timestamp. +bits and a 48-bit timestamp. It is designed with time-based sorting in mind, such as for database usage, as the highest bits are allocated from the timestamp of when it is created. @@ -141,13 +143,11 @@ generate_v7_basic :: proc(timestamp: Maybe(time.Time) = nil) -> (result: Identif assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR) unix_time_in_milliseconds := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 1e6 - temporary := cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT + result = transmute(Identifier)(cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT) bytes_generated := rand.read(result[6:]) assert(bytes_generated == 10, "RNG failed to generate 10 bytes for UUID v7.") - result |= transmute(Identifier)temporary - result[VERSION_BYTE_INDEX] &= 0x0F result[VERSION_BYTE_INDEX] |= 0x70 @@ -161,7 +161,7 @@ generate_v7_basic :: proc(timestamp: Maybe(time.Time) = nil) -> (result: Identif Generate a version 7 UUID that has an incremented counter. This UUID will be pseudorandom, save for 6 pre-determined version and variant -bits, a 48 bit timestamp, and 12 bits of counter state. +bits, a 48-bit timestamp, and 12 bits of counter state. It is designed with time-based sorting in mind, such as for database usage, as the highest bits are allocated from the timestamp of when it is created. @@ -183,7 +183,7 @@ Example: } Inputs: -- counter: A 12-bit value, incremented each time a UUID is generated in a batch. +- counter: A 12-bit value which should be incremented each time a UUID is generated in a batch. - timestamp: A timestamp from the `core:time` package, or `nil` to use the current time. Returns: @@ -191,17 +191,17 @@ Returns: */ generate_v7_with_counter :: proc(counter: u16, timestamp: Maybe(time.Time) = nil) -> (result: Identifier) { assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR) - assert(counter <= 0x0fff, "This implementation of the version 7 UUID does not support counters in excess of 12 bits (4,095).") + assert(counter <= 0x0fff, VERSION_7_BIG_COUNTER_ERROR) unix_time_in_milliseconds := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 1e6 - temporary := cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT - temporary |= cast(u128be)counter << VERSION_7_COUNTER_SHIFT + result = transmute(Identifier)( + cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT | + cast(u128be)counter << VERSION_7_COUNTER_SHIFT + ) bytes_generated := rand.read(result[8:]) assert(bytes_generated == 8, "RNG failed to generate 8 bytes for UUID v7.") - result |= transmute(Identifier)temporary - result[VERSION_BYTE_INDEX] &= 0x0F result[VERSION_BYTE_INDEX] |= 0x70 diff --git a/core/encoding/uuid/reading.odin b/core/encoding/uuid/reading.odin index c32f69eb7..d41606f63 100644 --- a/core/encoding/uuid/reading.odin +++ b/core/encoding/uuid/reading.odin @@ -113,7 +113,7 @@ clock_seq :: proc "contextless" (id: Identifier) -> (clock_seq: u16) { } /* -Get the node of a version 1 UUID. +Get the node of a version 1 or version 6 UUID. Inputs: - id: The identifier.