Skip to content

Instantly share code, notes, and snippets.

@ArvidSilverlock
Created January 28, 2025 10:48
Show Gist options
  • Select an option

  • Save ArvidSilverlock/ad15be9935621565af9cce6e22e137d6 to your computer and use it in GitHub Desktop.

Select an option

Save ArvidSilverlock/ad15be9935621565af9cce6e22e137d6 to your computer and use it in GitHub Desktop.
Read/write GUIDs from/to buffers in Luau. Will throw errors for invalid GUIDs if you use the 'strict' version. Depending on the specifics of your use case, if you really love hyper-optimisation you could probably remove the support for allowing/allowing no braces. It does encode the UUID compliance characters (the `4` and the `[89ab]`), but that…
local GUID_FORMAT = "%08x-%04x-%04x-%04x-%04x%08x"
local GUID_BRACES_FORMAT = "{" .. GUID_FORMAT .. "}"
local GUID_PATTERN = "^{?(%x%x%x%x%x%x%x%x)-(%x%x%x%x)-(4%x%x%x)-([89AaBb]%x%x%x)-(%x%x%x%x)(%x%x%x%x%x%x%x%x)}?$"
local function writeGUID(buff: buffer, offset: number, guid: string)
if guid:sub(1, 1) == "{" then
buffer.writeu32(buff, offset, tonumber(guid:sub(2, 9), 16))
buffer.writeu32(buff, offset + 4, tonumber(guid:sub(11, 14), 16) * 2 ^ 16 + tonumber(guid:sub(16, 19), 16))
buffer.writeu32(buff, offset + 8, tonumber(guid:sub(21, 24), 16) * 2 ^ 16 + tonumber(guid:sub(26, 29), 16))
buffer.writeu32(buff, offset + 12, tonumber(guid:sub(30, 37), 16))
else
buffer.writeu32(buff, offset, tonumber(guid:sub(1, 8), 16))
buffer.writeu32(buff, offset + 4, tonumber(guid:sub(10, 13), 16) * 2 ^ 16 + tonumber(guid:sub(15, 18), 16))
buffer.writeu32(buff, offset + 8, tonumber(guid:sub(20, 23), 16) * 2 ^ 16 + tonumber(guid:sub(25, 28), 16))
buffer.writeu32(buff, offset + 12, tonumber(guid:sub(29, 36), 16))
end
end
local function readGUID(buff: buffer, offset: number, braces: boolean?): string
local a = buffer.readu32(buff, offset)
local b = buffer.readu32(buff, offset + 4)
local c = buffer.readu32(buff, offset + 8)
local d = buffer.readu32(buff, offset + 12)
local format = if braces then GUID_BRACES_FORMAT else GUID_FORMAT
local guid = string.format(format, a, b // 2 ^ 16, b % 2 ^ 16, c // 2 ^ 16, c % 2 ^ 16, d)
return guid
end
local GUID_FORMAT = "%08x-%04x-%04x-%04x-%04x%08x"
local GUID_BRACES_FORMAT = "{" .. GUID_FORMAT .. "}"
local GUID_PATTERN = "^{?(%x%x%x%x%x%x%x%x)-(%x%x%x%x)-(4%x%x%x)-([89AaBb]%x%x%x)-(%x%x%x%x)(%x%x%x%x%x%x%x%x)}?$"
local INVALID_GUID_ERROR = "Invalid GUID"
local function writeGUID(buff: buffer, offset: number, guid: string)
local a, b, c, d, e, f = guid:match(GUID_PATTERN)
assert(a and b and c and d and e, INVALID_GUID_ERROR)
local firstBlock = assert(tonumber(a, 16), INVALID_GUID_ERROR)
local secondBlockA = assert(tonumber(b, 16), INVALID_GUID_ERROR)
local secondBlockB = assert(tonumber(c, 16), INVALID_GUID_ERROR)
local thirdBlockA = assert(tonumber(d, 16), INVALID_GUID_ERROR)
local thirdBlockB = assert(tonumber(e, 16), INVALID_GUID_ERROR)
local fourthBlock = assert(tonumber(f, 16), INVALID_GUID_ERROR)
buffer.writeu32(buff, offset, firstBlock)
buffer.writeu32(buff, offset + 4, secondBlockA * 2 ^ 16 + secondBlockB)
buffer.writeu32(buff, offset + 8, thirdBlockA * 2 ^ 16 + thirdBlockB)
buffer.writeu32(buff, offset + 12, fourthBlock)
end
local function readGUID(buff: buffer, offset: number, braces: boolean?): string
local a = buffer.readu32(buff, offset)
local b = buffer.readu32(buff, offset + 4)
local c = buffer.readu32(buff, offset + 8)
local d = buffer.readu32(buff, offset + 12)
local firstValidator = bit32.extract(b, 12, 4)
local secondValidator = bit32.extract(c, 28, 4)
assert(firstValidator == 4, INVALID_GUID_ERROR)
assert(secondValidator >= 8 and secondValidator <= 11, INVALID_GUID_ERROR)
local format = if braces then GUID_BRACES_FORMAT else GUID_FORMAT
local guid = string.format(format, a, b // 2 ^ 16, b % 2 ^ 16, c // 2 ^ 16, c % 2 ^ 16, d)
return guid
end
@ArvidSilverlock
Copy link
Author

what exactly is the use of this

Writing GUIDs to buffers (either for networking or data storage, as GUIDs are common in both areas), encoding them as binary rather than as strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment