web: Secondary utils and helpers
This commit is contained in:
87
packages/web/src/UUID.zig
Normal file
87
packages/web/src/UUID.zig
Normal file
@@ -0,0 +1,87 @@
|
||||
const std = @import("std");
|
||||
const UUID = @This();
|
||||
|
||||
bytes: [16]u8,
|
||||
|
||||
pub const zero: UUID = .{ .bytes = @splat(0) };
|
||||
|
||||
pub fn v4() UUID {
|
||||
var bytes: [16]u8 = undefined;
|
||||
std.crypto.random.bytes(&bytes);
|
||||
bytes[6] = (bytes[6] & 0x0F) | 0x40;
|
||||
bytes[8] = (bytes[8] & 0x3F) | 0x80;
|
||||
return .{ .bytes = bytes };
|
||||
}
|
||||
|
||||
pub const namespaces = struct {
|
||||
/// Name string is a fully-qualified domain name
|
||||
///
|
||||
/// `6ba7b810-9dad-11d1-80b4-00c04fd430c8`
|
||||
pub const dns: UUID = .{ .bytes = .{ 0x6B, 0xA7, 0xB8, 0x10, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8 } };
|
||||
/// Name string is a URL
|
||||
///
|
||||
/// `6ba7b811-9dad-11d1-80b4-00c04fd430c8`
|
||||
pub const url: UUID = .{ .bytes = .{ 0x6B, 0xA7, 0xB8, 0x11, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8 } };
|
||||
/// Name string is an ISO OID
|
||||
///
|
||||
/// `6ba7b812-9dad-11d1-80b4-00c04fd430c8`
|
||||
pub const oid: UUID = .{ .bytes = .{ 0x6B, 0xA7, 0xB8, 0x12, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8 } };
|
||||
/// Name string is an X.500 DN (in DER or a text output format)
|
||||
///
|
||||
/// `6ba7b814-9dad-11d1-80b4-00c04fd430c8`
|
||||
pub const x500: UUID = .{ .bytes = .{ 0x6B, 0xA7, 0xB8, 0x14, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8 } };
|
||||
};
|
||||
|
||||
pub fn v5(namespace: UUID, name: []const u8) UUID {
|
||||
const hash = blk: {
|
||||
var hasher = std.crypto.hash.Sha1.init(.{});
|
||||
hasher.update(namespace);
|
||||
hasher.update(name);
|
||||
break :blk hasher.finalResult();
|
||||
};
|
||||
|
||||
var bytes: [16]u8 = hash[0..16].*;
|
||||
bytes[6] = (bytes[6] & 0x0F) | 0x50;
|
||||
bytes[8] = (bytes[8] & 0x3F) | 0x80;
|
||||
|
||||
return .{ .bytes = bytes };
|
||||
}
|
||||
|
||||
var v7_lock: std.Thread.Mutex = .{};
|
||||
var v7_last_timestamp: std.atomic.Value(u64) = .{ .raw = 0 };
|
||||
var v7_counter: std.atomic.Value(u32) = .{ .raw = 0 };
|
||||
|
||||
fn getCount(timestamp: u64) u32 {
|
||||
v7_lock.lock();
|
||||
defer v7_lock.unlock();
|
||||
|
||||
if (v7_last_timestamp.swap(timestamp, .monotonic) != timestamp) {
|
||||
v7_counter.store(0, .monotonic);
|
||||
}
|
||||
|
||||
return v7_counter.fetchAdd(1, .monotonic) % 4096;
|
||||
}
|
||||
|
||||
pub fn v7() UUID {
|
||||
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 bytes: [16]u8 = undefined;
|
||||
bytes[0] = @truncate(timestamp >> 40);
|
||||
bytes[1] = @truncate(timestamp >> 32);
|
||||
bytes[2] = @truncate(timestamp >> 24);
|
||||
bytes[3] = @truncate(timestamp >> 16);
|
||||
bytes[4] = @truncate(timestamp >> 8);
|
||||
bytes[5] = @truncate(timestamp);
|
||||
bytes[6] = (@as(u8, 7) << 4) | @as(u8, @truncate((count >> 8) & 0x0F));
|
||||
bytes[7] = @truncate(count);
|
||||
bytes[8] = (random[0] & 0x3F) | 0x80;
|
||||
@memcpy(bytes[9..16], random[1..8]);
|
||||
|
||||
return .{ .bytes = bytes };
|
||||
}
|
||||
Reference in New Issue
Block a user