aboutsummaryrefslogtreecommitdiffhomepage
path: root/core/assert.lua
blob: cd2e013027c817ce21203fa4707927cff3d994b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
-- Copyright 2020-2022 Mitchell. See LICENSE.

--[[ This comment is for LuaDoc.
---
-- Extends `_G` with formatted assertions and function argument type checks.
module('assert')]]

---
-- Asserts that value *v* is not `false` or `nil` and returns *v*, or calls `error()` with
-- *message* as the error message, defaulting to "assertion failed!".
-- If *message* is a format string, the remaining arguments are passed to `string.format()`
-- and the resulting string becomes the error message.
-- @param v Value to assert.
-- @param message Optional error message to show on error. The default value is "assertion failed!".
-- @param ... If *message* is a format string, these arguments are passed to `string.format()`.
-- @name _G.assert
function assert(v, message, ...)
  if v then return v end
  if type(message) == 'string' and message:find('%%') then message = string.format(message, ...) end
  error(message or 'assertion failed!', 2)
end

---
-- Asserts that value *v* has type string *expected_type* and returns *v*, or calls `error()`
-- with an error message that implicates function argument number *narg*.
-- This is intended to be used with API function arguments so users receive more helpful error
-- messages.
-- @param v Value to assert the type of.
-- @param expected_type String type to assert. It may be a non-letter-delimited list of type
--   options.
-- @param narg The positional argument number *v* is associated with. This is not required to
--   be a number.
-- @usage assert_type(filename, 'string/nil', 1)
-- @usage assert_type(option.setting, 'number', 'setting') -- implicates key
-- @name _G.assert_type
function assert_type(v, expected_type, narg)
  if type(v) == expected_type then return v end
  -- Note: do not use assert for performance reasons.
  if type(expected_type) ~= 'string' then
    error(string.format("bad argument #2 to '%s' (string expected, got %s)",
      debug.getinfo(1, 'n').name, type(expected_type)), 2)
  elseif narg == nil then
    error(string.format("bad argument #3 to '%s' (value expected, got %s)",
      debug.getinfo(1, 'n').name, type(narg)), 2)
  end
  for type_option in expected_type:gmatch('%a+') do if type(v) == type_option then return v end end
  error(string.format("bad argument #%s to '%s' (%s expected, got %s)", narg,
    debug.getinfo(2, 'n').name or '?', expected_type, type(v)), 3)
end