mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-12 03:00:30 +00:00
Add utility to check table keys
expect.field acts very similarly to expect.expect, though checks a specific table key rather than a function argument.
This commit is contained in:
parent
865fc239a0
commit
10a27a7a25
@ -5,28 +5,29 @@
|
||||
|
||||
local native_select, native_type = select, type
|
||||
|
||||
--- Expect an argument to have a specific type.
|
||||
--
|
||||
-- @tparam number index The 1-based argument index.
|
||||
-- @param value The argument's value.
|
||||
-- @tparam string ... The allowed types of the argument.
|
||||
-- @throws If the value is not one of the allowed types.
|
||||
local function expect(index, value, ...)
|
||||
local t = native_type(value)
|
||||
for i = 1, native_select("#", ...) do
|
||||
if t == native_select(i, ...) then return true end
|
||||
end
|
||||
|
||||
local function get_type_names(...)
|
||||
local types = table.pack(...)
|
||||
for i = types.n, 1, -1 do
|
||||
if types[i] == "nil" then table.remove(types, i) end
|
||||
end
|
||||
|
||||
local type_names
|
||||
if #types <= 1 then
|
||||
type_names = tostring(...)
|
||||
return tostring(...)
|
||||
else
|
||||
type_names = table.concat(types, ", ", 1, #types - 1) .. " or " .. types[#types]
|
||||
return table.concat(types, ", ", 1, #types - 1) .. " or " .. types[#types]
|
||||
end
|
||||
end
|
||||
--- Expect an argument to have a specific type.
|
||||
--
|
||||
-- @tparam number index The 1-based argument index.
|
||||
-- @param value The argument's value.
|
||||
-- @tparam string ... The allowed types of the argument.
|
||||
-- @return The given `value`.
|
||||
-- @throws If the value is not one of the allowed types.
|
||||
local function expect(index, value, ...)
|
||||
local t = native_type(value)
|
||||
for i = 1, native_select("#", ...) do
|
||||
if t == native_select(i, ...) then return value end
|
||||
end
|
||||
|
||||
-- If we can determine the function name with a high level of confidence, try to include it.
|
||||
@ -36,6 +37,7 @@ local function expect(index, value, ...)
|
||||
if ok and info.name and #info.name ~= "" and info.what ~= "C" then name = info.name end
|
||||
end
|
||||
|
||||
local type_names = get_type_names(...)
|
||||
if name then
|
||||
error(("bad argument #%d to '%s' (expected %s, got %s)"):format(index, name, type_names, t), 3)
|
||||
else
|
||||
@ -43,4 +45,31 @@ local function expect(index, value, ...)
|
||||
end
|
||||
end
|
||||
|
||||
return { expect = expect }
|
||||
--- Expect an field to have a specific type.
|
||||
--
|
||||
-- @tparam table tbl The table to index.
|
||||
-- @tparam string index The field name to check.
|
||||
-- @tparam string ... The allowed types of the argument.
|
||||
-- @return The contents of the given field.
|
||||
-- @throws If the field is not one of the allowed types.
|
||||
local function field(tbl, index, ...)
|
||||
expect(1, tbl, "table")
|
||||
expect(2, index, "string")
|
||||
|
||||
local value = tbl[index]
|
||||
local t = native_type(value)
|
||||
for i = 1, native_select("#", ...) do
|
||||
if t == native_select(i, ...) then return value end
|
||||
end
|
||||
|
||||
if value == nil then
|
||||
error(("field '%s' missing from table"):format(index), 3)
|
||||
else
|
||||
error(("bad field '%s' (expected %s, got %s)"):format(index, get_type_names(...), t), 3)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
expect = expect,
|
||||
field = field,
|
||||
}
|
||||
|
@ -1,31 +1,53 @@
|
||||
describe("cc.expect", function()
|
||||
local e = require("cc.expect")
|
||||
|
||||
it("checks a single type", function()
|
||||
expect(e.expect(1, "test", "string")):eq(true)
|
||||
expect(e.expect(1, 2, "number")):eq(true)
|
||||
describe("expect", function()
|
||||
it("checks a single type", function()
|
||||
expect(e.expect(1, "test", "string")):eq("test")
|
||||
expect(e.expect(1, 2, "number")):eq(2)
|
||||
|
||||
expect.error(e.expect, 1, nil, "string"):eq("bad argument #1 (expected string, got nil)")
|
||||
expect.error(e.expect, 2, 1, "nil"):eq("bad argument #2 (expected nil, got number)")
|
||||
expect.error(e.expect, 1, nil, "string"):eq("bad argument #1 (expected string, got nil)")
|
||||
expect.error(e.expect, 2, 1, "nil"):eq("bad argument #2 (expected nil, got number)")
|
||||
end)
|
||||
|
||||
it("checks multiple types", function()
|
||||
expect(e.expect(1, "test", "string", "number")):eq("test")
|
||||
expect(e.expect(1, 2, "string", "number")):eq(2)
|
||||
|
||||
expect.error(e.expect, 1, nil, "string", "number"):eq("bad argument #1 (expected string or number, got nil)")
|
||||
expect.error(e.expect, 2, false, "string", "table", "number", "nil")
|
||||
:eq("bad argument #2 (expected string, table or number, got boolean)")
|
||||
end)
|
||||
|
||||
it("includes the function name", function()
|
||||
local function worker()
|
||||
expect(e.expect(1, nil, "string")):eq(true)
|
||||
end
|
||||
local function trampoline()
|
||||
worker()
|
||||
end
|
||||
|
||||
expect.error(trampoline):eq("expect_spec.lua:27: bad argument #1 to 'worker' (expected string, got nil)")
|
||||
end)
|
||||
end)
|
||||
|
||||
it("checks multiple types", function()
|
||||
expect(e.expect(1, "test", "string", "number")):eq(true)
|
||||
expect(e.expect(1, 2, "string", "number")):eq(true)
|
||||
describe("field", function()
|
||||
it("checks a single type", function()
|
||||
expect(e.field({ k = "test" }, "k", "string")):eq("test")
|
||||
expect(e.field({ k = 2 }, "k", "number")):eq(2)
|
||||
|
||||
expect.error(e.expect, 1, nil, "string", "number"):eq("bad argument #1 (expected string or number, got nil)")
|
||||
expect.error(e.expect, 2, false, "string", "table", "number", "nil")
|
||||
:eq("bad argument #2 (expected string, table or number, got boolean)")
|
||||
end)
|
||||
expect.error(e.field, { k = nil }, "k", "string"):eq("field 'k' missing from table")
|
||||
expect.error(e.field, { l = 1 }, "l", "nil"):eq("bad field 'l' (expected nil, got number)")
|
||||
end)
|
||||
|
||||
it("includes the function name", function()
|
||||
local function worker()
|
||||
expect(e.expect(1, nil, "string")):eq(true)
|
||||
end
|
||||
local function trampoline()
|
||||
worker()
|
||||
end
|
||||
it("checks multiple types", function()
|
||||
expect(e.field({ k = "test" }, "k", "string", "number")):eq("test")
|
||||
expect(e.field({ k = 2 }, "k", "string", "number")):eq(2)
|
||||
|
||||
expect.error(trampoline):eq("expect_spec.lua:26: bad argument #1 to 'worker' (expected string, got nil)")
|
||||
expect.error(e.field, { k = nil }, "k", "string", "number")
|
||||
:eq("field 'k' missing from table")
|
||||
expect.error(e.field, { l = false }, "l", "string", "table", "number", "nil")
|
||||
:eq("bad field 'l' (expected string, table or number, got boolean)")
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user