1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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
|