From 39dde41516b09182391a4a8afbe6819b2eff419f Mon Sep 17 00:00:00 2001 From: BONNAURE Olivier Date: Fri, 12 Apr 2024 17:10:27 +0200 Subject: [PATCH] [Redbean] Add UuidV4 method (#1140) --- test/tool/net/uuidv4_test.lua | 25 +++++++++++++++++++++++++ tool/net/definitions.lua | 4 ++++ tool/net/help.txt | 3 +++ tool/net/lfuncs.c | 25 +++++++++++++++++++++++++ tool/net/lfuncs.h | 1 + tool/net/redbean.c | 1 + 6 files changed, 59 insertions(+) create mode 100644 test/tool/net/uuidv4_test.lua diff --git a/test/tool/net/uuidv4_test.lua b/test/tool/net/uuidv4_test.lua new file mode 100644 index 000000000..08b4ac3c7 --- /dev/null +++ b/test/tool/net/uuidv4_test.lua @@ -0,0 +1,25 @@ +-- Copyright 2024 Justine Alexandra Roberts Tunney +-- +-- Permission to use, copy, modify, and/or distribute this software for +-- any purpose with or without fee is hereby granted, provided that the +-- above copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +-- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +-- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +-- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +-- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +-- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +-- PERFORMANCE OF THIS SOFTWARE. +for i = 1, 1000000 do + local uuid = UuidV4() + assert(#uuid == 36) + assert(string.sub(uuid, 9, 9) == "-") + assert(string.sub(uuid, 14, 14) == "-") + assert(string.sub(uuid, 15, 15) == "4") + assert(string.sub(uuid, 19, 19) == "-") + y = string.sub(uuid, 20, 20) + assert(y == "8" or y == "9" or y == "a" or y == "b") + assert(string.sub(uuid, 24, 24) == "-") +end diff --git a/tool/net/definitions.lua b/tool/net/definitions.lua index 988e3ba6f..f6fecffda 100644 --- a/tool/net/definitions.lua +++ b/tool/net/definitions.lua @@ -1977,6 +1977,10 @@ function VisualizeControlCodes(str) end ---@nodiscard function Underlong(str) end +--- Generate a uuid_v4 +--- @return string +function UuidV4() end + ---@param x integer ---@return integer # position of first bit set. --- Passing `0` will raise an error. Same as the Intel x86 instruction BSF. diff --git a/tool/net/help.txt b/tool/net/help.txt index 8095149cd..ab6af435d 100644 --- a/tool/net/help.txt +++ b/tool/net/help.txt @@ -1062,6 +1062,9 @@ FUNCTIONS Server Name Indicator (SNI) when performing Fetch() requests. This function is not available in unsecure mode. + UuidV4() -> str + Returns an uuid v4 string. + Fetch(url:str[,body:str|{method=value:str,body=value:str,headers=table,...}]) ├─→ status:int, {header:str=value:str,...}, body:str └─→ nil, error:str diff --git a/tool/net/lfuncs.c b/tool/net/lfuncs.c index 1949f1649..79f0d1ca0 100644 --- a/tool/net/lfuncs.c +++ b/tool/net/lfuncs.c @@ -829,6 +829,31 @@ int LuaVisualizeControlCodes(lua_State *L) { return LuaCoder(L, VisualizeControlCodes); } +int LuaUuidV4(lua_State *L) { + static const char v[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + char uuid_str[37] = {0}; + uint64_t r = _rand64(); + int j = 0; + for (int i = 0; i < 36; ++i, ++j) { + if (j == 16) { + r = _rand64(); + j = 0; + } + uuid_str[i] = v[(r & (0xfull << (j * 4ull))) >> (j * 4ull)]; + } + + uuid_str[8] = '-'; + uuid_str[13] = '-'; + uuid_str[14] = '4'; + uuid_str[18] = '-'; + uuid_str[19] = v[8 | (r & (0x3ull << (j * 4ull))) >> (j * 4ull)]; + uuid_str[23] = '-'; + uuid_str[36] = '\0'; + lua_pushfstring(L, uuid_str); + return 1; +} + static dontinline int LuaHasherImpl(lua_State *L, size_t k, int H(const void *, size_t, uint8_t *)) { size_t n; diff --git a/tool/net/lfuncs.h b/tool/net/lfuncs.h index c5fcf8796..ab82c4e95 100644 --- a/tool/net/lfuncs.h +++ b/tool/net/lfuncs.h @@ -90,6 +90,7 @@ int LuaSleep(lua_State *); int LuaSlurp(lua_State *); int LuaUncompress(lua_State *); int LuaUnderlong(lua_State *); +int LuaUuidV4(lua_State *); int LuaVisualizeControlCodes(lua_State *); void LuaPushUrlView(lua_State *, struct UrlView *); diff --git a/tool/net/redbean.c b/tool/net/redbean.c index e3c741b7a..144e0dcbd 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -5287,6 +5287,7 @@ static const luaL_Reg kLuaFuncs[] = { {"StoreAsset", LuaStoreAsset}, // {"Uncompress", LuaUncompress}, // {"Underlong", LuaUnderlong}, // + {"UuidV4", LuaUuidV4}, // {"VisualizeControlCodes", LuaVisualizeControlCodes}, // {"Write", LuaWrite}, // {"bin", LuaBin}, //