uuid

tape
import uuid from "uuid";

let id: uuid.Uuid = uuid.v4() or {
    io.println("no entropy: {err}");
    return 1;
};
io.println(id.format());                 // "919108f7-52d1-4320-9bac-f847db4148a8"

let key: uuid.Uuid = uuid.v7(time.unix_nanos() / 1000000) or { return 1; };   // sorts by time

let u: uuid.Uuid = uuid.parse("\{F81D4FAE-7DEC-11D0-A765-00A0C91E6BF6\}") or {
    io.println("bad id: {err}");          // "not a UUID"
    return 1;
};

A Uuid is the 16 bytes of RFC 9562, in the order the text writes them. It is a plain value: copy it, compare it, keep it in a struct; nothing to free.

uuid is a capability module, but only because v4 and v7 read the operating system’s random source. Everything else only computes.

Making one

FunctionGives
v4()A random UUID (version 4), or io.IoError if the OS has no entropy to give
v7(unix_ms)A time-ordered UUID (version 7): the time in milliseconds, then random bits, or io.IoError
nil()00000000-0000-0000-0000-000000000000
max()ffffffff-ffff-ffff-ffff-ffffffffffff
from_bytes(b)The UUID of exactly 16 bytes, or UuidError for any other length

Pick v4 for an identifier nobody can guess or order, v7 for keys you want sorted by when they were made, such as database rows. v7 takes the time from you, so a test can pass a fixed one; it stops the program with a trap for a negative time or one past 48 bits (the year 10889).

id.as_bytes() gives the 16 bytes back as a []const u8, a view into id.

Text

parse(text) reads a UUID in any of these forms, with hex digits in either case:

FormExample
hyphenatedf81d4fae-7dec-11d0-a765-00a0c91e6bf6
32 digitsf81d4fae7dec11d0a76500a0c91e6bf6
in braces{f81d4fae-7dec-11d0-a765-00a0c91e6bf6}
URNurn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6

Anything else is UuidError.Malformed (“not a UUID”): a missing or extra digit, a letter past f, a hyphen in the wrong place, one brace without the other, spaces around it.

id.format() writes it back hyphenated and in lower case; id.write(&b) appends the same 36 characters to a str.Builder.

tape
var b: str.Builder = str.builder();
b.append("order ");
u.write(&b);
let line: string = b.finish();           // "order f81d4fae-7dec-11d0-a765-00a0c91e6bf6"

Fields

MethodReturns
id.version()1 to 8, the version the bits say; 0 for nil, max and UUIDs of another variant
id.variant()0 NCS, 1 RFC 9562 (every UUID made today), 2 Microsoft, 3 reserved
id.unix_ms()The time in a v7, in milliseconds since 1970
id.is_nil()Whether every bit is zero
tape
let k: uuid.Uuid = uuid.v7(1645557742000) or { return 1; };
io.println("{k.version()} {k.unix_ms()}");   // "7 1645557742000"

Comparing and map keys

a.eq(&b) is true for the same 16 bytes. a.less(&b) orders byte by byte, which is the order of the text, so v7s made in different milliseconds sort by time. Two v7s made in the same millisecond have no particular order.

a.hash() hashes the bytes. To key a collections map or set by Uuid, pass the function forms uuid_hash and uuid_eq:

tape
import collections from "collections";

@tape { collections.gen_map_by(uuid.Uuid, string, uuid.uuid_hash, uuid.uuid_eq); }

var names: Map_Uuid_string = map_Uuid_string_new();
names.set(u, "Ada");
let n: string = names.get(u)!;           // "Ada"

Last modified: