use std::{marker::PhantomData, sync::Arc}; use mlua::{FromLua, IntoLua, Lua, Result, Value}; use crate::lua::ownedfunction::OwnedFunction; #[derive(Clone, Debug)] 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: IntoLua<'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: IntoLua<'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: IntoLua<'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), } } }