Aleksei-bird 7c9c708c92 Первый фикс
Пачки некоторых позиций увеличены
2024-03-01 20:54:33 +03:00

459 lines
12 KiB
Lua

--- Is expression library
-- @module Utils.Is
-- @usage
-- local Is = require('__stdlib__/stdlib/utils/is')
-- Is.True(true)
-- Is.Not.True(false)
-- Is.Assert.True(true)
-- Is.Assert.Not.True(false)
--- Is Table
-- @section Table
--- Is the test true.
-- @table Is
-- @field Not Is the test not true.
-- @field Assert Assert that the test is true.
-- @field Assert.Not Assert that the test is not true.
--- Is Table Callers
-- @section Callers
--- Is the test truthy
-- @function Is
-- @tparam mixed var
-- @treturn boolean
local Is = {}
--- Is the test not truthy
-- @function Not
-- @tparam mixed var
-- @treturn boolean
Is.Not = {}
--- Assert that the test is Truthy
-- @function Assert
-- @tparam mixed var
-- @treturn boolean
Is.Assert = {}
--- Assert that the test is not Truthy
-- @function Assert.Not
-- @tparam mixed var
-- @treturn boolean
Is.Assert.Not = {}
--- Functions
-- @section Functions
local M = {}
local type = type
local floor = math.floor
local huge = math.huge
--- Returns the var if the passed variable is a table.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Table(var)
return type(var) == 'table' and var
end
M.table = M.Table
--- Returns the var if the passed variable is a string.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.String(var)
return type(var) == 'string' and var
end
M.string = M.String
--- Returns the var if the passed variable is a number.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Number(var)
return type(var) == 'number' and var
end
M.number = M.Number
function M.Thread(var)
return type(var) == 'thread' and var
end
M.thread = M.Thread
function M.Userdata(var)
return type(var) == 'userdata' and var
end
M.userdata = M.Userdata
--- Returns true if the passed variable is nil.
-- @tparam mixed var The variable to check
-- @treturn boolean
function M.Nil(var)
return type(var) == 'nil'
end
M.is_nil = M.Nil
--- Returns true if the passed variable is a boolean.
-- @tparam mixed var The variable to check
-- @treturn boolean
function M.Boolean(var)
return type(var) == 'boolean'
end
M.boolean = M.boolean
--- Returns true if the passed variable is true
-- @tparam mixed var The variable to check
-- @treturn boolean
function M.True(var)
return var == true
end
M.is_true = M.True
--- Returns the var if the passed variable is not nil or false.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Truthy(var)
return var or false
end
M.truthy = M.Truthy
--- Returns true if the passed variable is false.
-- @tparam mixed var The variable to check
-- @treturn boolean
function M.False(var)
return var == false
end
M.is_false = M.False
--- Returns true if the passed variable is false or nil.
-- @tparam mixed var The variable to check
-- @treturn boolean
function M.Falsy(var)
return not var
end
M.falsy = M.Falsy
--- Returns true if the passed variable is nil, an empty table, or an empty string.
-- @tparam mixed var The variable to check
-- @treturn boolean
function M.Empty(var)
if M.Table(var) then
return table_size and table_size(var) == 0 or next(var) == nil
elseif M.String(var) then
return #string == 0
end
return M.Nil(var)
end
M.empty = M.Empty
function M.None(var)
return M.Empty(var) or M.False(var) or var == 0 or var ~= var
end
M.none = M.None
--- Returns the passed var if it is positive.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Positive(var)
return M.Number(var) and var >= 0 and var
end
M.positive = M.Positive
--- Returns the passed var if it is odd.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.odd(var)
return M.number(var) and (var % 2 ~= 0) and var
end
--- Returns the passed var if it is even.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.even(var)
return M.number(var) and (var % 2 == 0) and var
end
--- Returns the passed var if it is negative.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Negative(var)
return M.Number(var) and var < 0 and var
end
M.negative = M.Negative
--- Returns the passed var if it is not a number.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.NaN(var)
return var ~= var
end
M.nan = M.NaN
--- Returns the passed var if it is finite.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Finite(var)
return M.Number(var) and (var < huge and var > -huge) and var
end
M.finite = M.Finite
--- Returns the passed var if it is an int.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Int(var)
return M.Finite(var) and rawequal(floor(var), var) and var
end
M.int = M.Int
--- Returns the passed var if it is an int8.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Int8(var)
return M.Int(var) and var >= -128 and var <= 127 and var
end
M.int8 = M.Int8
--- Returns the passed var if it is an int16.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Int16(var)
return M.Int(var) and var >= -32768 and var <= 32767 and var
end
M.int16 = M.Int16
--- Returns the passed var if it is an int32.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Int32(var)
return M.Int(var) and var >= -2147483648 and var <= 2147483647 and var
end
M.int32 = M.Int32
--- Returns the passed var if it is an unsigned int.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Unsigned(var)
return Is.Number(var) and (var < huge and var >= 0) and var
end
M.unsigned = M.Unsigned
--- Returns the passed var if it is an unsigned int.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.UInt(var)
return M.Unsigned(var) and rawequal(floor(var), var) and var
end
M.uint = M.UInt
--- Returns the passed var if it is an unsigned int8.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.UInt8(var)
return M.UInt(var) and var <= 255 and var
end
M.uint8 = M.UInt8
--- Returns the passed var if it is an unsigned int16.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.UInt16(var)
return M.UInt(var) and var <= 65535 and var
end
M.uint16 = M.UInt16
--- Returns the passed var if it is an unsigned int32.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.UInt32(var)
return M.UInt(var) and var <= 4294967295 and var
end
M.uint32 = M.UInt32
--- Returns the passed var if it is a float.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Float(var)
return M.number(var) and var >= 0 and var < 1 and var
end
M.float = M.Float
--- Returns the passed var if it is a full position.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Position(var)
return M.Table(var) and (var.x and var.y) and var
end
M.position = M.Position
--- Returns the passed var if it is a full area.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Area(var)
return M.Table(var) and (M.Position(var.left_top) and M.Position(var.right_bottom)) and var
end
M.area = M.Area
--- Returns the passed var if it is a simple position/vector.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Vector(var)
return M.Table(var) and ((M.Number(var[1]) and M.Number(var[2])) or M.Position(var)) and var
end
M.vector = M.Vector
--- Returns the passed var if it is a simple area/boundingbox.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.BoundingBox(var)
return M.Table(var) and (M.Vector(var[1]) and M.Vector(var[2]))
end
M.boundingbox = M.BoundingBox
M.bounding_box = M.BoundingBox
M.Bounding_Box = M.BoundingBox
--- Returns the hex value of the passed var if it is hexadecimal.
-- @tparam mixed var The variable to check
-- @treturn mixed
function M.Hex(var)
return M.String(var) and var:match('%x%x%x%x%x%x$')
end
M.hex = M.Hex
--- Returns true if the passed variable is a single alphbetical word.
-- Does not allow any special chars
-- @tparam mixed var The variable to check
-- @treturn boolean true if the passed variable is a single alphbetical word
function M.StrictWord(var)
return M.String(var) and var:find('^[%a]+$') == 1
end
M.strict_word = M.StrictWord
--- Returns true if the passed variable is a single alphbetical word.
-- Allows _ and - as part of the word
-- @tparam mixed var The variable to check
-- @treturn boolean true if the passed variable is a single alphbetical word
function M.AlphabetWord(var)
return M.String(var) and var:find('^[%a%_%-]+$') == 1
end
M.Word = M.AlphabetWord
--- Returns true if the passed variable is a single alphbetical word.
-- Must start with a letter, allows _ and - as part of the word
-- @tparam mixed var The variable to check
-- @treturn boolean true if the passed variable is a single alphbetical word
function M.AlphanumWord(var)
return M.String(var) and var:find('^%a+[%w%_%-]*$') == 1
end
M.Alpha = M.AlphanumWord
M.alpha = M.AlphanumWord
M.alphanumword = M.AlphanumWord
--- Is this a factorio object
-- @tparam LuaObject var The variable to check
-- @treturn mixed the var if this is an LuaObject
function M.Object(var)
return M.Table(var) and var.__self and var
end
M.object = M.Object
--- Is this factorio object valid
-- @tparam LuaObject var The variable to check
-- @treturn mixed the var if this is a valid LuaObject
function M.Valid(var)
return M.Object(var) and var.valid and var
end
M.valid = M.Valid
--- Returns true if the passed variable is a callable function.
-- @tparam mixed var The variable to check
-- @treturn boolean true if the passed variable is a callable function
function M.Callable(var)
return type(var) == 'function' or type((getmetatable(var) or {}).__call) == 'function'
end
M.callable = M.Callable
M.Function = M.Callable
M.is_function = M.Callable
setmetatable(
Is,
{
__index = function(_, k)
return M[k] and function(_assert)
return M[k](_assert)
end or nil
end,
__call = function(_, ...)
return (...)
end
}
)
setmetatable(
Is.Not,
{
__index = function(_, k)
return M[k] and function(_assert)
return not M[k](_assert)
end or nil
end,
__call = function(_, ...)
return not (...)
end
}
)
Is.is_not = Is.Not
-- convenience function for un-lambda-ing deferred error messages
local function safe_invoke(f)
local ok, msg = xpcall(f, debug.traceback)
if not ok then
-- ensure msg really is a string so there is theoretically no chance
-- of a triple fault (i.e.: from a monkey-patched debug.traceback
-- returning something that now fails to concatenate to a string)
if type(msg) == 'string' then
msg = '<<< DOUBLE FAULT: ' .. msg .. ' >>>'
end
end
-- for sanity-preservation, always return something truthy
return msg or 'Unknown Error'
end
setmetatable(
Is.Assert,
{
__index = function(_, k)
return M[k] and function(_assert, _message, _level)
_level = tonumber(_level) or 3 ---@type integer
return M[k](_assert) or error(type(_message) == 'function' and safe_invoke(_message) or _message or 'assertion failed', _level)
end or nil
end,
__call = function(_, ...)
local param = { ... }
local _level = tonumber(param[3]) or 3 --[[@as integer]]
return param[1] or error(type(param[2]) == 'function' and safe_invoke(param[2]) or param[2] or 'assertion failed', _level)
end
}
)
Is.assert = Is.Assert
setmetatable(
Is.Assert.Not,
{
__index = function(_, k)
return M[k] and function(_assert, _message, _level)
_level = tonumber(_level) or 3 ---@type integer
return not M[k](_assert) or error(type(_message) == 'function' and safe_invoke(_message) or _message or 'assertion failed', _level)
end or nil
end,
__call = function(_, ...)
local param = { ... }
local _level = tonumber(param[3]) or 3 --[[@as integer]]
return not param[1] or error(type(param[2]) == 'function' and safe_invoke(param[2]) or param[2] or 'assertion failed', _level)
end
}
)
Is.assert.is_not = Is.Assert.Not
return Is