Jump to content

Module:table/getMetamethod

From Wiktionary, the free dictionary

local table_get_unprotected_metatable = "Module:table/getUnprotectedMetatable"

local rawget = rawget
local select = select

local function get_unprotected_metatable(...)
	get_unprotected_metatable = require(table_get_unprotected_metatable)
	return get_unprotected_metatable(...)
end

local function get_metamethod(n, i, mt, mm, ...)
	if mt then
		mm = rawget(mt, mm)
	else
		mm = nil
	end
	if i == n then
		return mm
	end
	return mm, get_metamethod(n, i + 1, mt, ...)
end

--[==[
Takes an input value and any number of metamethods, and attempts to retrieve the values at those keys in the value's metatable. Returns a boolean stating whether the value's metamethods are findable, followed by a return value for each metamethod.

A value's metamethods are findable if it does not have a protected metatable, so the first return value is {true} if the value either has a metatable which does not contain the {__metatable} metamethod, or it has no metatable at all. If the value does have a protected metatable, the first return value is {false}, and all remaining return values default to {nil}.]==]
return function(t, ...)
	local mt, n = get_unprotected_metatable(t), select("#", ...)
	-- get_unprotected_metatable() returns the metatable if it's unprotected,
	-- false if it's protected, or nil if there is no metatable. It checks
	-- whether a metatable is protected by trying pcall(setmetatable, t),
	-- so it's always possible to determine accurately.
	if n == 0 then
		return mt ~= false
	end
	return mt ~= false, get_metamethod(n, 1, mt, ...)
end