Implementation of TypeID in Lua
1local UUID7 = {}
2local millitime = require("millitime")
3
4local VERSION_7 = 0x7000
5local VARIANT_RFC4122 = 0x8000
6
7-- generate a UUIDv7 as a length 16 table of one-byte integers
8function UUID7.as_table(timestamp, seed)
9 -- use current time if no timestamp provided
10 timestamp = timestamp or millitime.time()
11 -- seed is for tests
12 math.randomseed(seed or millitime.time())
13
14 -- extract low 48 bits/6 bytes from timestamp
15 local ts = timestamp & 0xffffffffffff
16
17 -- random for the remaining 80 bits/10 bytes
18 local r7 = math.random(0, 0xff)
19 local r8 = math.random(0, 0xff)
20 local r9 = math.random(0, 0xff)
21 local r10 = math.random(0, 0xff)
22 local r11 = math.random(0, 0xff)
23 local r12 = math.random(0, 0xff)
24 local r13 = math.random(0, 0xff)
25 local r14 = math.random(0, 0xff)
26 local r15 = math.random(0, 0xff)
27 local r16 = math.random(0, 0xff)
28
29 return {
30 -- bytes 1-6: timestamp (48 bits)
31 (ts >> 40) & 0xff,
32 (ts >> 32) & 0xff,
33 (ts >> 24) & 0xff,
34 (ts >> 16) & 0xff,
35 (ts >> 8) & 0xff,
36 ts & 0xff,
37
38 -- 7th byte: random mask with version 7
39 (VERSION_7 >> 8) | (r7 & 0x0f),
40
41 -- 8th byte: random
42 r8,
43
44 -- 9th byte: random mask with variant
45 0x80 | (r9 & VARIANT_RFC4122),
46
47 -- 10th byte: random
48 r10,
49
50 -- 6 bytes 11-12: random
51 r11, r12, r13, r14, r15, r16
52 }
53end
54
55-- convert a 16-byte table to a standard UUID string
56function UUID7.to_string(bytes)
57 if not bytes or #bytes ~= 16 then
58 error("UUID must be a 16-byte table")
59 end
60
61 return string.format(
62 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
63 bytes[1], bytes[2], bytes[3], bytes[4],
64 bytes[5], bytes[6],
65 bytes[7], bytes[8],
66 bytes[9], bytes[10],
67 bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], bytes[16]
68 )
69end
70
71
72-- generate a UUIDv7 as a standard UUID string
73function UUID7.generate(timestamp, seed)
74 return UUID7.to_string(UUID7.as_table(timestamp, seed))
75end
76
77return UUID7