mlua-rs / rlua

High level Lua bindings to Rust
Other
1.72k stars 115 forks source link

Context.create_sequence_from should support references #267

Closed mpdelbuono closed 7 months ago

mpdelbuono commented 1 year ago

Context::create_sequence_from currently requires a parameter of type IntoIterator<Item = T>. When using this to define methods for userdata from its attribute, preferably a borrowed reference could be used to construct the sequence, for example:

struct Foo {
    pub val: Vec<i32>
} ;

impl UserData for Foo {
    fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
        methods.add_method("foo", |l, this, _: ()| {
            let table = l.create_sequence_from(&this.val); // legal because this.val only needs to exist during execution
            return Ok(table)
        });
    }
}

Because there is no longevity of the supplied value required (the Lua table is constructed and filled immediately), this is a safe operation; the Lua table can outlive the userdata from which it was constructed. Without this support, users are forced either to (1) take a performance hit for copying the vec, or (2) manually construct the table.

Proposal is to add an overload to create_sequence_from() to allow for passing a reference.

jugglerchris commented 1 year ago

Hi, &Vec<T> already implements IntoIterator<Item=&T>, so it's not the IntoIterator which is the problem - in this example it's that &i32 doesn't implement ToLua.

For this example, you can do:

let table = l.create_sequence_from(this.val.iter().cloned());

But maybe your real types aren't as simple and cheaply clonable than i32?