42 lines
1.1 KiB
Zig
42 lines
1.1 KiB
Zig
const std = @import("std");
|
|
|
|
var lock: std.Thread.Mutex = .{};
|
|
var last_timestamp: std.atomic.Value(u64) = .{ .raw = 0 };
|
|
var counter: std.atomic.Value(u32) = .{ .raw = 0 };
|
|
|
|
fn getCount(timestamp: u64) u32 {
|
|
lock.lock();
|
|
defer lock.unlock();
|
|
|
|
if (last_timestamp.swap(timestamp, .monotonic) != timestamp) {
|
|
counter.store(0, .monotonic);
|
|
}
|
|
|
|
return counter.fetchAdd(1, .monotonic) % 4096;
|
|
}
|
|
|
|
pub fn uuid_v7() [16]u8 {
|
|
const timestamp: u64 = @intCast(@max(0, std.time.milliTimestamp()));
|
|
const count = getCount(timestamp);
|
|
const random = blk: {
|
|
var bytes: [8]u8 = undefined;
|
|
std.crypto.random.bytes(&bytes);
|
|
break :blk bytes;
|
|
};
|
|
|
|
var res: [16]u8 = undefined;
|
|
|
|
res[0] = @truncate(timestamp >> 40);
|
|
res[1] = @truncate(timestamp >> 32);
|
|
res[2] = @truncate(timestamp >> 24);
|
|
res[3] = @truncate(timestamp >> 16);
|
|
res[4] = @truncate(timestamp >> 8);
|
|
res[5] = @truncate(timestamp);
|
|
res[6] = (@as(u8, 7) << 4) | @as(u8, @truncate((count >> 8) & 0x0F));
|
|
res[7] = @truncate(count);
|
|
res[8] = 0x80 | (random[0] & 0x3F);
|
|
@memcpy(res[9..16], random[1..8]);
|
|
|
|
return res;
|
|
}
|