Add `has_metamethod` to `AnyUserData`

This commit is contained in:
Alex Orlenko 2020-05-24 02:23:05 +01:00
parent c3822219e0
commit a9a4cf13f1
2 changed files with 23 additions and 1 deletions

View File

@ -10,7 +10,7 @@ use crate::lua::Lua;
use crate::table::Table;
use crate::types::{LuaRef, MaybeSend};
use crate::util::{assert_stack, get_userdata, StackGuard};
use crate::value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti};
use crate::value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti, Value};
/// Kinds of metamethods that can be overridden.
///
@ -460,6 +460,22 @@ impl<'lua> AnyUserData<'lua> {
V::from_lua(res, lua)
}
/// Checks for a metamethod in this `AnyUserData`
pub fn has_metamethod(&self, method: MetaMethod) -> Result<bool> {
match self.get_metatable() {
Ok(mt) => {
let name = self.0.lua.create_string(method.name())?;
if let Value::Nil = mt.raw_get(name)? {
Ok(false)
} else {
Ok(true)
}
}
Err(Error::UserDataTypeMismatch) => Ok(false),
Err(e) => Err(e),
}
}
fn get_metatable(&self) -> Result<Table<'lua>> {
unsafe {
let lua = self.0.lua;

View File

@ -166,6 +166,12 @@ fn test_metamethods() -> Result<()> {
assert!(userdata2 != userdata3); // because references are differ
assert!(userdata2.equals(userdata3)?);
let userdata1: AnyUserData = globals.get("userdata1")?;
assert!(userdata1.has_metamethod(MetaMethod::Add)?);
assert!(userdata1.has_metamethod(MetaMethod::Sub)?);
assert!(userdata1.has_metamethod(MetaMethod::Index)?);
assert!(!userdata1.has_metamethod(MetaMethod::Pow)?);
Ok(())
}