-- 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 "" 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