aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--spec/util_uuid_spec.lua22
-rw-r--r--util/uuid.lua17
2 files changed, 39 insertions, 0 deletions
diff --git a/spec/util_uuid_spec.lua b/spec/util_uuid_spec.lua
index 46400d00..7157d0ec 100644
--- a/spec/util_uuid_spec.lua
+++ b/spec/util_uuid_spec.lua
@@ -20,6 +20,28 @@ describe("util.uuid", function()
for _ = 1, 100 do
assert.is_string(uuid.generate():match(pattern));
end
+
+ assert.truthy(uuid.generate() ~= uuid.generate(), "does not generate the same UUIDv4 twice")
+ end);
+ end);
+ describe("#v7", function()
+ it("should also follow the UUID pattern", function()
+ local pattern = "^" .. table.concat({
+ string.rep("%x", 8),
+ string.rep("%x", 4),
+ "7" .. -- version
+ string.rep("%x", 3),
+ "[89ab]" .. -- reserved bits of 1 and 0
+ string.rep("%x", 3),
+ string.rep("%x", 12),
+ }, "%-") .. "$";
+
+ local one = uuid.v7(); -- one before the loop to ensure some time passes
+ for _ = 1, 100 do
+ assert.is_string(uuid.v7():match(pattern));
+ end
+ -- one after the loop when some time should have passed
+ assert.truthy(one < uuid.v7(), "should be ordererd")
end);
end);
end);
diff --git a/util/uuid.lua b/util/uuid.lua
index 41c2e9cd..a70750bb 100644
--- a/util/uuid.lua
+++ b/util/uuid.lua
@@ -8,8 +8,10 @@
local random = require "prosody.util.random";
local random_bytes = random.bytes;
+local time = require "prosody.util.time";
local hex = require "prosody.util.hex".encode;
local m_ceil = math.ceil;
+local m_floor = math.floor;
local function get_nibbles(n)
return hex(random_bytes(m_ceil(n/2))):sub(1, n);
@@ -24,7 +26,22 @@ local function generate()
return get_nibbles(8).."-"..get_nibbles(4).."-4"..get_nibbles(3).."-"..(get_twobits())..get_nibbles(3).."-"..get_nibbles(12);
end
+local function generate_v7()
+ -- Sortable based on time and random
+ -- https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-01#section-4.4
+ local t = time.now();
+ local unixts = m_floor(t);
+ local unixts_a = m_floor(unixts / 16);
+ local unixts_b = m_floor(unixts % 16);
+ local subsec = t % 1;
+ local subsec_a = m_floor(subsec * 0x1000);
+ local subsec_b = m_floor(subsec * 0x1000000) % 0x1000;
+ return ("%08x-%x%03x-7%03x-%4s-%12s"):format(unixts_a, unixts_b, subsec_a, subsec_b, get_twobits() .. get_nibbles(3), get_nibbles(12));
+end
+
return {
+ v4 = generate;
+ v7 = generate_v7;
get_nibbles=get_nibbles;
generate = generate ;
-- COMPAT