aboutsummaryrefslogtreecommitdiff
path: root/src/util.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.lua')
-rw-r--r--src/util.lua142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/util.lua b/src/util.lua
new file mode 100644
index 0000000..f74953a
--- /dev/null
+++ b/src/util.lua
@@ -0,0 +1,142 @@
+--[[
+Various helpful functions
+]]
+local util = {}
+function util.cartesian(...)
+ -- cartesian(tbl1, tbl2, tbl3, ...)
+ -- for each table, returns a permutation of key, value in tbl1, tbl2, ect.
+ local args = {...}
+ return coroutine.wrap(function()
+ local cursors = {} -- cursors[1], cursors[3], ect. are the keys
+ for k,v in ipairs(args) do
+ local a,b = next(v,nil)
+ cursors[(k*2) - 1] = a
+ cursors[(k*2)] = b
+ end
+ coroutine.yield(unpack(cursors))
+ local any_left = true
+ while any_left do
+ while next(args[#args],cursors[#cursors - 1]) do
+ local a,b = next(args[#args],cursors[#cursors - 1])
+ cursors[#cursors - 1] = a
+ cursors[#cursors] = b
+ coroutine.yield(unpack(cursors))
+ end
+ any_left = false
+ for i = #args, 1, -1 do
+ if next(args[i],cursors[(i*2)-1]) then
+ cursors[(i*2)-1], cursors[i*2] = next(args[i],cursors[(i*2)-1])
+ for j = i+1, #args do
+ cursors[(j*2)-1], cursors[j*2] = next(args[j],nil)
+ end
+ coroutine.yield(unpack(cursors))
+ any_left = true
+ break
+ end
+ end
+ end
+ end)
+end
+
+-- Override tostring to display more info about the table
+local old_tostring = tostring
+local numtabs = 0
+local printed_tables = {}
+local function tostring_helper(el)
+ assert(type(el) == "table", "Tried to call helper with something that was not a table, it was a " .. type(el))
+ local mt = getmetatable(el)
+ if mt and mt.__tostring then
+ return mt.__tostring(el)
+ elseif printed_tables[el] == true then
+ return old_tostring(el)
+ else
+ printed_tables[el] = true
+ numtabs = numtabs + 1
+ local strbuilder = {"{"}
+ for k,v in pairs(el) do
+ local key,value
+ if type(k) == "table" then
+ key = tostring_helper(k)
+ else
+ key = old_tostring(k)
+ end
+ if type(v) == "table" then
+ value = tostring_helper(v)
+ else
+ value = old_tostring(v)
+ end
+ strbuilder[#strbuilder + 1] = string.format("%s%s : %s", string.rep("\t",numtabs), key, value)
+ end
+ strbuilder[#strbuilder + 1] = string.rep("\t",numtabs - 1) .. "}"
+ numtabs = numtabs - 1
+ return table.concat(strbuilder,"\n")
+ end
+
+end
+function tostring(el)
+ printed_tables = {}
+ if type(el) == "table" then
+ return tostring_helper(el)
+ end
+ return old_tostring(el)
+end
+
+function util.reverse(tbl, val)
+ val = val or true
+ local ret = {}
+ for _,v in ipairs(tbl) do
+ ret[v] = val
+ end
+ return ret
+end
+
+function util.typecheck(tbl, ...)
+ local args = {...}
+ assert(#args % 2 == 0,"Typecheck should have an odd number of arguments, found " .. tostring(#args + 1) .. ".")
+ for i = 1, #args, 2 do
+ assert(args[i] and type(args[i]) == "string", "Cannot check a field of type " .. type(args[i]) .. " at position " .. tostring(i + 1) .. ".")
+ assert(tbl[args[i]], "Failed to find a field: " .. args[i])
+ assert(args[i+1] and type(args[i + 1]) == "string", "Cannot check for a type " .. type(args[i + 1]) .. " at position " .. tostring(i + 2) .. ".")
+ assert(type(tbl[args[i]]) == args[i+1], "Expected a " .. args[i+1] .. " at position " .. tostring(i+2) .. " but found a " .. type(tbl[args[i]]))
+ end
+ return true
+end
+
+function util.peer_to_code(str)
+ -- Turn peerjs peer ids into shorter strings
+ -- Example: 0dbbe67a-5358-4ea2-910a-195754b556a7
+ -- = 16 bytes
+ local buffer = am.buffer(16)
+ local view = buffer:view("ubyte")
+ local i = 0
+ for byte in str:gmatch("%x%x") do
+ local n = tonumber(byte,16)
+ view[(i % 16) + 1] = n
+ i = i + 1
+ end
+ local encoded = am.base64_encode(buffer)
+ return encoded:gsub("[/+]",{["/"] = "-",["+"] = "_"}):sub(1,22) -- chop the last 2 glyphs, assume 16 bytes
+end
+
+function util.code_to_peer(str)
+ local padded = str:gsub("[_-]",{["-"] = "/", ["_"] = "+"}) .. "=="
+ local buffer = am.base64_decode(padded)
+ local view = buffer:view("ubyte")
+ local dashes = {4,2,2,2,6}
+ local builder = {}
+ local i = 1
+ while #dashes > 0 do
+ local nbytes = table.remove(dashes,1)
+ for _ = 1, nbytes do
+ table.insert(builder, string.format("%02x",view[i]))
+ i = i + 1
+ end
+ if #dashes > 0 then
+ table.insert(builder,"-")
+ end
+ end
+ ret = table.concat(builder)
+ return ret
+end
+
+return util