You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.9 KiB
82 lines
2.9 KiB
-- Lua-side of the utils module.
|
|
-- utils.NULL, utils.isNull, utils.toJSON, utils.fromJSON are provided by Rust before this runs.
|
|
|
|
local NIL_ERROR_PLACEHOLDER = "unspecified error"
|
|
|
|
-- Pretty-print any Lua value as a string.
|
|
local function dumpValue(val, depth, seen)
|
|
if depth > 20 then return "..." end
|
|
local t = type(val)
|
|
if t == "nil" then
|
|
return "nil"
|
|
elseif t == "boolean" or t == "number" then
|
|
return tostring(val)
|
|
elseif t == "string" then
|
|
return string.format("%q", val)
|
|
elseif t == "table" then
|
|
if utils.isNull(val) then return "null" end
|
|
if seen[val] then return "<circular>" end
|
|
seen[val] = true
|
|
local parts = {}
|
|
local len = #val
|
|
if len > 0 then
|
|
for i = 1, len do
|
|
parts[i] = dumpValue(val[i], depth + 1, seen)
|
|
end
|
|
else
|
|
for k, v in pairs(val) do
|
|
local key = type(k) == "string" and k or ("[" .. tostring(k) .. "]")
|
|
parts[#parts + 1] = key .. " = " .. dumpValue(v, depth + 1, seen)
|
|
end
|
|
end
|
|
seen[val] = nil
|
|
if #parts == 0 then return "{}" end
|
|
return "{ " .. table.concat(parts, ", ") .. " }"
|
|
else
|
|
return "<" .. t .. ">"
|
|
end
|
|
end
|
|
|
|
--- Pretty-print any Lua value to a string.
|
|
function utils.dump(val)
|
|
return dumpValue(val, 0, {})
|
|
end
|
|
|
|
--- Call a function, capturing any error. Returns (result, nil) on success or (nil, err) on failure.
|
|
--- Extra arguments are forwarded to the callback, like pcall.
|
|
function utils.try(callback, ...)
|
|
if type(callback) ~= "function" then
|
|
error("utils.try: callback is not a function (got " .. type(callback) .. ")")
|
|
end
|
|
local ok, result = pcall(callback, ...)
|
|
if ok then return result, nil end
|
|
if result == nil then result = NIL_ERROR_PLACEHOLDER end
|
|
return nil, result
|
|
end
|
|
|
|
local TRYN_MAX_COUNT = 64
|
|
|
|
--- Like utils.try but for functions that return N values.
|
|
--- Returns (v1, ..., vN, nil) on success or (nil, ..., nil, err) on failure.
|
|
function utils.tryn(expectedCount, callback, ...)
|
|
local count = math.tointeger(expectedCount)
|
|
if count == nil then error("utils.tryn: expectedCount must be an integer number") end
|
|
expectedCount = count
|
|
if expectedCount < 0 then error("utils.tryn: expectedCount must not be negative") end
|
|
if expectedCount > TRYN_MAX_COUNT then
|
|
error("utils.tryn: at most " .. TRYN_MAX_COUNT .. " return values are supported")
|
|
end
|
|
if type(callback) ~= "function" then
|
|
error("utils.tryn: callback is not a function (got " .. type(callback) .. ")")
|
|
end
|
|
local results = table.pack(pcall(callback, ...))
|
|
if results[1] then
|
|
results[expectedCount + 2] = nil
|
|
return table.unpack(results, 2, expectedCount + 2)
|
|
end
|
|
local err = results[2]
|
|
if err == nil then err = NIL_ERROR_PLACEHOLDER end
|
|
local out = {}
|
|
out[expectedCount + 1] = err
|
|
return table.unpack(out, 1, expectedCount + 1)
|
|
end
|
|
|