summaryrefslogtreecommitdiff
path: root/src/lua/evalsto.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/evalsto.rs')
-rw-r--r--src/lua/evalsto.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/lua/evalsto.rs b/src/lua/evalsto.rs
new file mode 100644
index 0000000..6d8ab29
--- /dev/null
+++ b/src/lua/evalsto.rs
@@ -0,0 +1,85 @@
+use std::{fmt, marker::PhantomData, sync::Arc};
+
+use mlua::{FromLua, IntoLua, Lua, Result, Value};
+
+use crate::lua::ownedfunction::OwnedFunction;
+
+#[derive(Clone)]
+pub enum EvalTo<T, A> {
+ Function(Arc<OwnedFunction>, PhantomData<A>),
+ Value(T),
+}
+
+impl<T, A> EvalTo<T, A> {
+ pub fn get<'lua>(&'lua self, args: A, lua: &'lua Lua) -> Result<T>
+ 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<T, A>
+where
+ T: FromLua<'lua> + Clone,
+ A: IntoLua<'lua>,
+{
+ fn from_lua(
+ value: mlua::prelude::LuaValue<'lua>,
+ lua: &'lua mlua::prelude::Lua,
+ ) -> Result<Self> {
+ 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<T, A>
+where
+ T: FromLua<'lua> + Clone + IntoLua<'lua>,
+ A: IntoLua<'lua>,
+{
+ fn into_lua(self, lua: &'lua mlua::prelude::Lua) -> Result<Value<'lua>> {
+ match self {
+ EvalTo::Function(value, _) => Ok(value.get(lua).into_lua(lua)?),
+ EvalTo::Value(value) => value.into_lua(lua),
+ }
+ }
+}
+
+impl<T, A> Default for EvalTo<T, A>
+where
+ T: Default,
+{
+ fn default() -> Self {
+ Self::Value(T::default())
+ }
+}
+
+impl<T, A> fmt::Debug for EvalTo<T, A>
+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),
+ }
+ }
+}