mirror of
https://github.com/1bardesign/batteries.git
synced 2024-11-25 07:04:35 +00:00
119 lines
2.5 KiB
Lua
119 lines
2.5 KiB
Lua
--[[
|
|
various intuitive assertions that
|
|
- avoid garbage generation upon success,
|
|
- build nice formatted error messages
|
|
- post one level above the call site by default
|
|
- return their first argument so they can be used inline
|
|
|
|
default call is builtin global assert
|
|
|
|
can call nop() to dummy out everything for "release mode"
|
|
(if you're worried about that sort of thing)
|
|
]]
|
|
|
|
local _assert = assert
|
|
|
|
--proxy calls to global assert
|
|
local assert = setmetatable({}, {
|
|
__call = function(self, ...)
|
|
return _assert(...)
|
|
end,
|
|
})
|
|
|
|
local function _extra(msg)
|
|
if not msg then
|
|
return ""
|
|
end
|
|
return "\n\n\t(note: " .. msg .. ")"
|
|
end
|
|
|
|
--assert a value is not nil
|
|
--return the value, so this can be chained
|
|
function assert:some(v, msg, stack_level)
|
|
if v == nil then
|
|
error(("assertion failed: value is nil %s"):format(
|
|
_extra(msg)
|
|
), 2 + (stack_level or 0))
|
|
end
|
|
return v
|
|
end
|
|
|
|
--assert two values are equal
|
|
function assert:equal(a, b, msg, stack_level)
|
|
if a ~= b then
|
|
error(("assertion failed: %s is not equal to %s %s"):format(
|
|
tostring(a),
|
|
tostring(b),
|
|
_extra(msg)
|
|
), 2 + (stack_level or 0))
|
|
end
|
|
return a
|
|
end
|
|
|
|
--assert two values are not equal
|
|
function assert:not_equal(a, b, msg, stack_level)
|
|
if a == b then
|
|
error(("assertion failed: values are equal %s"):format(
|
|
_extra(msg)
|
|
), 2 + (stack_level or 0))
|
|
end
|
|
return a
|
|
end
|
|
|
|
--assert a value is of a certain type
|
|
function assert:type(a, t, msg, stack_level)
|
|
if type(a) ~= t then
|
|
error(("assertion failed: %s (%s) not of type %s %s"):format(
|
|
tostring(a),
|
|
type(a),
|
|
tostring(t),
|
|
_extra(msg)
|
|
), 2 + (stack_level or 0))
|
|
end
|
|
return a
|
|
end
|
|
|
|
--assert a value is nil or a certain type.
|
|
-- useful for optional parameters.
|
|
function assert:type_or_nil(a, t, msg, stack_level)
|
|
if a ~= nil then
|
|
assert:type(a, t, msg, stack_level + 1)
|
|
end
|
|
return a
|
|
end
|
|
|
|
--assert a value is one of those in a table of options
|
|
function assert:one_of(a, t, msg, stack_level)
|
|
for _, value in ipairs(t) do
|
|
if value == a then
|
|
return a
|
|
end
|
|
end
|
|
|
|
local values = {}
|
|
for index = 1, #t do
|
|
values[index] = tostring(t[index])
|
|
end
|
|
|
|
error(("assertion failed: %s not one of %s %s"):format(
|
|
tostring(a),
|
|
table.concat(values, ", "),
|
|
_extra(msg)
|
|
), 2 + (stack_level or 0))
|
|
end
|
|
|
|
--replace everything in assert with nop functions that just return their second argument, for near-zero overhead on release
|
|
function assert:nop()
|
|
local nop = function(_, a)
|
|
return a
|
|
end
|
|
setmetatable(self, {
|
|
__call = nop,
|
|
})
|
|
for k, v in pairs(self) do
|
|
self[k] = nop
|
|
end
|
|
end
|
|
|
|
return assert
|