use std::{fmt, marker::PhantomData, sync::Arc}; use mlua::{FromLua, IntoLua, IntoLuaMulti, Lua, Result, Value}; use crate::lua::ownedfunction::OwnedFunction; #[derive(Clone)] pub enum EvalTo { Function(Arc, PhantomData), Value(T), } impl EvalTo { pub fn get<'lua>(&'lua self, args: A, lua: &'lua Lua) -> Result where T: FromLua<'lua> + Clone, A: IntoLuaMulti<'lua>, { match self { EvalTo::Function(value, _) => { let func = value.get(lua); T::from_lua(func.call(args)?, lua) } EvalTo::Value(value) => Ok(value.clone()), } } pub const fn new(value: T) -> Self { Self::Value(value) } } impl<'lua, T, A> FromLua<'lua> for EvalTo where T: FromLua<'lua> + Clone, A: IntoLuaMulti<'lua>, { fn from_lua( value: mlua::prelude::LuaValue<'lua>, lua: &'lua mlua::prelude::Lua, ) -> Result { if value.is_function() { Ok(Self::Function( Arc::new(OwnedFunction::new(value, lua)), PhantomData, )) } else { Ok(Self::Value(T::from_lua(value, lua)?)) } } } impl<'lua, T, A> IntoLua<'lua> for EvalTo where T: FromLua<'lua> + Clone + IntoLua<'lua>, A: IntoLuaMulti<'lua>, { fn into_lua(self, lua: &'lua mlua::prelude::Lua) -> Result> { match self { EvalTo::Function(value, _) => Ok(value.get(lua).into_lua(lua)?), EvalTo::Value(value) => value.into_lua(lua), } } } impl Default for EvalTo where T: Default, { fn default() -> Self { Self::Value(T::default()) } } impl fmt::Debug for EvalTo where T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { EvalTo::Function(_, _) => write!(f, "function"), EvalTo::Value(v) => v.fmt(f), } } }