Skip to content

Implementing UserData and FromLua for non Copyable/Clonable structs #599

@oezingle

Description

@oezingle

Hi All,

I must admit I'm quite new to both Rust and mlua. I'm familiar with C/C++ and read the Rust documentation book up to chapter 7. After deciding that I should just get my toes wet.

I've started my first project - a Lua module port of wasmtime, with the eventual goal of writing a loader to integrate WASM modules with lua. I could skip a bunch of steps here by writing the loader entirely in Rust, but I was hoping to port the wasmtime API so I could provide a WebAssembly API in Lua similar to JavaScript. However, I'm getting very stuck with the (absurdly underdocumented IMO) UserData and FromLua traits.

Here's my naive approach to get the wasmtime::Engine struct to be accessible from the Lua side.

use mlua::{
    Lua,
    
    UserData, FromLua,
    
    Table, Function, Value,
};
use mlua::prelude::LuaResult;

use wasmtime::Engine;

#[derive(Copy)]
pub struct LuaEngine {
    internal: Engine,
}

impl LuaEngine {
    fn default () -> LuaResult<LuaEngine> {
        return Ok(LuaEngine {
            internal: Engine::default(),
        });
    }

    pub fn get (&self) -> &Engine {
        return &self.internal;
    }
}

impl UserData for LuaEngine {
}

impl FromLua for LuaEngine {
    fn from_lua(value: Value, _: &Lua) -> LuaResult<Self> {
        match value {
            Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
            _ => unreachable!(),
        }
    }
}

// I'm using a table here because I'd prefer the module to publish 
// 'structs-as-tables' when possible, in keeping with lua's style
pub fn register_engine (lua: &Lua) -> LuaResult<Table> {
    let engine = lua.create_table()?;

    engine.set("default", Function::wrap(LuaEngine::default))?;

    return Ok(engine);
}

Compiling causes a build error - wasmtime::Engine does not implement std::marker::Copy. I'm sort of lost at this point. I need LuaEngine to implement FromLua because of wasmtime::Module::from_file(engine: &Engine, path: String) (and its eventual Lua counterpart).

How can I get around this restriction? I want a LuaEngine instance to essentially be a reference to a wasmtime::Engine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions