mlua-rs/mlua

Difficulty deserializing Lua functions with mlua

tickox opened this issue · 6 comments

Hello,

I am new to Rust and trying to use mlua. I am having difficulty deserializing Lua functions in Rust. What steps are necessary to make this work correctly?

In case of an error due to extra or missing fields, is it possible to identify which Lua line is causing the problem to facilitate debugging ?

Here is an example code:

#[derive(Deserialize)]
struct Test<'lua> {
    name: String,
    callback: Option<Function<'lua>>,
}

fn main() -> Result<()> {
    let lua = Lua::new();

    let lua_file = r#"
    {
        "name"= "test",
        "callback"= function(table)
            print("ok")
        end
    }
    "#;

    let test: Test = lua.from_value(lua.load(lua_file).eval()?)?;

    Ok(())
}

Thank you for your help!

Functions does not support serializations/deserializations through serde.

Would be better to implement FromLua for the Test struct.

sort of:

impl<'lua> FromLua<'lua> for Test<'lua> {
  fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
     let table = value.as_table().unwrap();
     Ok(Test {
        name: table.get("name")?,
        callback: table.get("callback")?
      })
  }
}

Ok thanks you

The solution above seems not to work with lifetime issues. Also trying to implement with extensive lifetime annotations does not help :-(

use mlua::{FromLua, Function, Lua, LuaSerdeExt, Result, Value};
use serde_derive::Deserialize;

#[derive(Deserialize)]
struct Test<'lua> {
    name: String,
    callback: Option<Function<'lua>>,
}

impl<'lua> FromLua<'lua> for Test<'lua> {
    fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
        let table = value.as_table().unwrap();
        let name: String = table.get("name")?;
        let callback: Option<Function<'lua>> = table.get("callback")?;
        Ok(Test { name, callback })
    }
}

fn main() -> Result<()> {
    let lua = Lua::new();

    let lua_file = r#" {
        name= "test",
        callback= function(table)
            print("ok")
        end
    }
    "#;

    let test: Test = lua.from_value(lua.load(lua_file).eval()?)?;

    Ok(())
}

@PatWie
try this:

use mlua::{FromLua, Function, Lua, Result, Table, Value};

#[derive(Debug)]
struct Test<'lua> {
    name: String,
    callback: Option<Function<'lua>>,
}

impl<'lua> FromLua<'lua> for Test<'lua> {
    fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
        let table: Table = lua.unpack(value)?;
        let name = table.get("name")?;
        let callback = table.get("callback")?;
        Ok(Test { name, callback })
    }
}

fn main() -> Result<()> {
    let lua = Lua::new();

    let lua_file = r#" {
        name= "test",
        callback= function(table)
            print("ok")
        end
    }
    "#;

    let test: Test = lua.load(lua_file).eval()?;
    println!("{test:?}");

    Ok(())
}

I just realised that lifetime in Value::as_table is wrong because they point to self lifetime instead of 'lua (Table<'self> but should be Table<'lua>)

Also you can try v0.10-beta that does not have any lifetimes.

Holy moly,
that version is awesome! This is unblocking me in my own language-server project with LLMs, Lua, Rust. Thanks a lot!!!