Skip to content

Instantly share code, notes, and snippets.

@coolaj86
Last active September 21, 2024 08:17
Show Gist options
  • Save coolaj86/5e32233cff533d899a3fa77a1ec6d0dd to your computer and use it in GitHub Desktop.
Save coolaj86/5e32233cff533d899a3fa77a1ec6d0dd to your computer and use it in GitHub Desktop.
uuidv7 draft in zig (fixed enough to compile, but not all the way)

See https://buildkite.com/blog/goodbye-integers-hello-uuids

image

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           unix_ts_ms                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          unix_ts_ms           |  ver  |       rand_a          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |var|                        rand_b                             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                            rand_b                             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# zig 0.14.0-dev.1511+54b668f8a (2024-09-12)
# Copyright 2024 AJ ONeal <[email protected]>
# Licensed under MPL-2.0
# Repo at https://github.com/coolaj86/zig-uuidv7
#!/bin/sh
# libc targets do not need to link against external libc
#
b_libc_targets="aarch64-linux-android
aarch64-linux-gnu
aarch64-linux-musl
aarch64-macos-none
aarch64-windows-gnu
aarch64_be-linux-gnu
aarch64_be-linux-musl
arm-linux-gnu
arm-linux-gnueabi
arm-linux-gnueabihf
arm-linux-musleabi
arm-linux-musleabihf
armeb-linux-gnueabi
armeb-linux-gnueabihf
armeb-linux-musleabi
armeb-linux-musleabihf
loongarch64-linux-gnu
loongarch64-linux-musl
mips-linux-gnueabi
mips-linux-gnueabihf
mips-linux-musleabi
mips-linux-musleabihf
mips64-linux-gnuabi64
mips64-linux-gnuabin32
mips64-linux-musl
mips64el-linux-gnuabi64
mips64el-linux-gnuabin32
mips64el-linux-musl
mipsel-linux-gnueabi
mipsel-linux-gnueabihf
mipsel-linux-musleabi
mipsel-linux-musleabihf
powerpc-linux-gnueabi
powerpc-linux-gnueabihf
powerpc-linux-musleabi
powerpc-linux-musleabihf
powerpc64-linux-gnu
powerpc64-linux-musl
powerpc64le-linux-gnu
powerpc64le-linux-musl
riscv32-linux-gnu
riscv32-linux-musl
riscv64-linux-gnu
riscv64-linux-musl
thumb-linux-musleabi
thumb-linux-musleabihf
thumb-windows-gnu
thumbeb-linux-musleabi
thumbeb-linux-musleabihf
wasm32-wasi-musl
wasm32-wasi-none
x86-linux-gnu
x86-linux-musl
x86-windows-gnu
x86_64-linux-gnu
x86_64-linux-gnux32
x86_64-linux-musl
x86_64-macos-none
x86_64-windows-gnu"
# However, these libc targets were removed because they failed
#
# ERROR: wasm32-freestanding-musl
# ERROR: sparc64-linux-gnu
# ERROR: sparc-linux-gnu
# ERROR: s390x-linux-musl
# ERROR: s390x-linux-gnu
# ERROR: m68k-linux-musl
# ERROR: m68k-linux-gnu
# ERROR: csky-linux-gnueabihf
# ERROR: csky-linux-gnueabi
for b_target in ${b_libc_targets}; do
echo >&2 "${b_target}"
zig build-exe ./uuidv7.zig -O ReleaseSmall -target "${b_target}" -femit-bin="uuidv7-${b_target}"
done
# these non-libc targets require a libc to link against
#
# ERROR: aarch64-freebsd-gnu
# ERROR: aarch64-ios-none
# ERROR: aarch64-netbsd-gnu
# ERROR: aarch64-openbsd-gnu
# ERROR: arm-plan9-none
# ERROR: powerpc64-aix-none
# ERROR: s390x-linux-gnu
# ERROR: wasm32-freestanding-none
# ERROR: x86-freebsd-gnu
# ERROR: x86-netbsd-gnu
# ERROR: x86-openbsd-gnu
# ERROR: x86-plan9-none
# ERROR: x86_64-dragonfly-none
# ERROR: x86_64-freebsd-gnu
# ERROR: x86_64-illumos-none
# ERROR: x86_64-netbsd-gnu
# ERROR: x86_64-openbsd-gnu
# ERROR: x86_64-plan9-none
# ERROR: x86_64-solaris-none
// zig 0.14.0-dev.1511+54b668f8a (2024-09-12)
// zig build-exe uuidv7.zig -O ReleaseSmall -femit-bin=uuidv7
// Copyright 2024 (c) AJ ONeal
// Licensed under the MPL-2.0
const std = @import("std");
const builtin = @import("builtin");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const getrandom = if (builtin.os.tag == .windows) std.os.windows.RtlGenRandom else std.posix.getrandom;
const uuid7 = try generateUUIDv7(getrandom);
const uuid7str = try uuidToString(uuid7);
try stdout.print("{s}\n", .{uuid7str});
}
pub const UUID = struct {
time_high: u32,
time_low: u16,
version_random1: u16,
variant_random2: u16,
random3: u16,
random4: u32,
};
fn generateUUIDv7(getrandom: anytype) !UUID {
// Get the current Unix timestamp in milliseconds
const inow = std.time.milliTimestamp();
const now: u64 = @intCast(inow); // we use 48 bits
const time_low: u16 = @truncate(now);
const time_high: u32 = @truncate(now >> 16);
const version = (0b111 << 12); // 0b111 is the 7 in UUIDv7
const version_mask = 0x0FFF;
const variant = (0b10 << 14); // 0b10 is the endianness-indicating variant
const variant_mask = 0b0011111111111111;
var random_bytes: [10]u8 = undefined;
try getrandom(&random_bytes);
const version_random1: u16 = (((@as(u16, random_bytes[0]) << 8) | @as(u16, random_bytes[1])) &
version_mask) | version;
const variant_random2: u16 = ((((@as(u16, random_bytes[2]) << 8) | @as(u16, random_bytes[3])) &
variant_mask)) | variant;
const random3: u16 = (@as(u16, random_bytes[4]) << 8) | @as(u16, random_bytes[5]);
const random4: u32 = (@as(u32, random_bytes[6]) << 24) |
(@as(u32, random_bytes[7]) << 16) |
(@as(u32, random_bytes[8]) << 8) |
@as(u32, random_bytes[9]);
return UUID{
.time_high = time_high,
.time_low = time_low,
.version_random1 = version_random1,
.variant_random2 = variant_random2,
.random3 = random3,
.random4 = random4,
};
}
fn uuidToString(uuid: UUID) ![]const u8 {
var buffer: [36]u8 = undefined;
// time_h32-t_16-verh-varh-rand03rand04
// 019212d3-87f4-7d25-902e-b8d39fe07f08
return std.fmt.bufPrint(&buffer, "{x:08}-{x}-{x}-{x:04}-{x:04}{x:08}", .{ uuid.time_high, uuid.time_low, uuid.version_random1, uuid.variant_random2, uuid.random3, uuid.random4 });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment