#![allow(clippy::missing_errors_doc)] use std::{any::type_name, cell::RefCell, fmt, ops}; use mlua::prelude::*; // Utility functions type ListWriter = dyn Fn(&mut fmt::Formatter<'_>, bool, &str) -> fmt::Result; #[must_use] pub fn make_list_writer() -> Box { let first = RefCell::new(true); Box::new(move |f, flag, literal| { if flag { if first.take() { write!(f, "{literal}")?; } else { write!(f, ", {literal}")?; } } Ok::<_, fmt::Error>(()) }) } /* Userdata metamethod implementations Note that many of these return [`LuaResult`] even though they don't return any errors - this is for consistency reasons and to make it easier to add these blanket implementations to [`LuaUserData`] impls. */ pub fn userdata_impl_to_string(_: &Lua, datatype: &D, _: ()) -> LuaResult where D: LuaUserData + ToString + 'static, { Ok(datatype.to_string()) } pub fn userdata_impl_eq(_: &Lua, datatype: &D, value: LuaValue) -> LuaResult where D: LuaUserData + PartialEq + 'static, { if let LuaValue::UserData(ud) = value { if let Ok(value_as_datatype) = ud.borrow::() { Ok(*datatype == *value_as_datatype) } else { Ok(false) } } else { Ok(false) } } pub fn userdata_impl_unm(_: &Lua, datatype: &D, _: ()) -> LuaResult where D: LuaUserData + ops::Neg + Copy, { Ok(-*datatype) } pub fn userdata_impl_add(_: &Lua, datatype: &D, value: LuaUserDataRef) -> LuaResult where D: LuaUserData + ops::Add + Copy, { Ok(*datatype + *value) } pub fn userdata_impl_sub(_: &Lua, datatype: &D, value: LuaUserDataRef) -> LuaResult where D: LuaUserData + ops::Sub + Copy, { Ok(*datatype - *value) } pub fn userdata_impl_mul_f32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult where D: LuaUserData + ops::Mul + ops::Mul + Copy + 'static, { match &rhs { LuaValue::Number(n) => return Ok(*datatype * *n as f32), LuaValue::Integer(i) => return Ok(*datatype * *i as f32), LuaValue::UserData(ud) => { if let Ok(vec) = ud.borrow::() { return Ok(*datatype * *vec); } } _ => {} } Err(LuaError::FromLuaConversionError { from: rhs.type_name(), to: type_name::().to_string(), message: Some(format!( "Expected {} or number, got {}", type_name::(), rhs.type_name() )), }) } pub fn userdata_impl_mul_i32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult where D: LuaUserData + ops::Mul + ops::Mul + Copy + 'static, { match &rhs { LuaValue::Number(n) => return Ok(*datatype * *n as i32), LuaValue::Integer(i) => return Ok(*datatype * *i), LuaValue::UserData(ud) => { if let Ok(vec) = ud.borrow::() { return Ok(*datatype * *vec); } } _ => {} } Err(LuaError::FromLuaConversionError { from: rhs.type_name(), to: type_name::().to_string(), message: Some(format!( "Expected {} or number, got {}", type_name::(), rhs.type_name() )), }) } pub fn userdata_impl_div_f32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult where D: LuaUserData + ops::Div + ops::Div + Copy + 'static, { match &rhs { LuaValue::Number(n) => return Ok(*datatype / *n as f32), LuaValue::Integer(i) => return Ok(*datatype / *i as f32), LuaValue::UserData(ud) => { if let Ok(vec) = ud.borrow::() { return Ok(*datatype / *vec); } } _ => {} } Err(LuaError::FromLuaConversionError { from: rhs.type_name(), to: type_name::().to_string(), message: Some(format!( "Expected {} or number, got {}", type_name::(), rhs.type_name() )), }) } pub trait IDiv { type Output; #[must_use] fn idiv(self, rhs: Rhs) -> Self::Output; } pub fn userdata_impl_idiv_f32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult where D: LuaUserData + IDiv + IDiv + Copy + 'static, { match &rhs { LuaValue::Number(n) => return Ok(datatype.idiv(*n as f32)), LuaValue::Integer(i) => return Ok(datatype.idiv(*i as f32)), LuaValue::UserData(ud) => { if let Ok(vec) = ud.borrow::() { return Ok(datatype.idiv(*vec)); } } _ => {} } Err(LuaError::FromLuaConversionError { from: rhs.type_name(), to: type_name::().to_string(), message: Some(format!( "Expected {} or number, got {}", type_name::(), rhs.type_name() )), }) } pub fn userdata_impl_div_i32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult where D: LuaUserData + ops::Div + ops::Div + Copy + 'static, { match &rhs { LuaValue::Number(n) => return Ok(*datatype / *n as i32), LuaValue::Integer(i) => return Ok(*datatype / *i), LuaValue::UserData(ud) => { if let Ok(vec) = ud.borrow::() { return Ok(*datatype / *vec); } } _ => {} } Err(LuaError::FromLuaConversionError { from: rhs.type_name(), to: type_name::().to_string(), message: Some(format!( "Expected {} or number, got {}", type_name::(), rhs.type_name() )), }) }