Lua runner with rich builtin stdlib
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.
 
 
a/lua/stdlib/utils.lua

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