Skip to content

Commit 9891e86

Browse files
committed
Remove Clone requirement from UserDataFields::add_field()
1 parent e3c5cfd commit 9891e86

3 files changed

Lines changed: 36 additions & 26 deletions

File tree

src/state/raw.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,9 @@ impl RawLua {
805805
rawset_field(state, -2, MetaMethod::validate(&k)?)?;
806806
}
807807
let mut has_name = false;
808-
for (k, f) in registry.meta_fields {
808+
for (k, push_field) in registry.meta_fields {
809809
has_name = has_name || k == MetaMethod::Type;
810-
let rawlua = mem::transmute::<&RawLua, &RawLua>(self);
811-
mlua_assert!(f(rawlua, 0)? == 1, "field function must return one value");
810+
push_field(self)?;
812811
rawset_field(state, -2, MetaMethod::validate(&k)?)?;
813812
}
814813
// Set `__name/__type` if not provided
@@ -832,31 +831,38 @@ impl RawLua {
832831
ffi::lua_pop(state, 1);
833832
push_table(state, 0, fields_nrec, true)?;
834833
}
835-
for (k, f) in registry.fields {
836-
let rawlua = mem::transmute::<&RawLua, &RawLua>(self);
837-
mlua_assert!(f(rawlua, 0)? == 1, "field function must return one value");
834+
for (k, push_field) in mem::take(&mut registry.fields) {
835+
push_field(self)?;
838836
rawset_field(state, -2, &k)?;
839837
}
840838
rawset_field(state, metatable_index, "__index")?;
841839
}
842840
_ => {
843841
ffi::lua_pop(state, 1);
844-
// Propagate fields to the field getters
845-
for (k, f) in registry.fields {
846-
registry.field_getters.push((k, f))
847-
}
842+
// Fields will be converted to functions and added to field getters
848843
}
849844
}
850845
}
851846

852847
let mut field_getters_index = None;
853-
let field_getters_nrec = registry.field_getters.len();
848+
let field_getters_nrec = registry.field_getters.len() + registry.fields.len();
854849
if field_getters_nrec > 0 {
855850
push_table(state, 0, field_getters_nrec, true)?;
856851
for (k, m) in registry.field_getters {
857852
self.push(self.create_callback(m)?)?;
858853
rawset_field(state, -2, &k)?;
859854
}
855+
for (k, push_field) in registry.fields {
856+
unsafe extern "C-unwind" fn return_field(state: *mut ffi::lua_State) -> c_int {
857+
ffi::lua_pushvalue(state, ffi::lua_upvalueindex(1));
858+
1
859+
}
860+
push_field(self)?;
861+
protect_lua!(state, 1, 1, fn(state) {
862+
ffi::lua_pushcclosure(state, return_field, 1);
863+
})?;
864+
rawset_field(state, -2, &k)?;
865+
}
860866
field_getters_index = Some(ffi::lua_absindex(state, -1));
861867
extra_tables_count += 1;
862868
}

src/userdata.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ pub trait UserDataFields<T> {
467467
/// be used as a fall-back if no regular field or method are found.
468468
fn add_field<V>(&mut self, name: impl ToString, value: V)
469469
where
470-
V: IntoLua + Clone + 'static;
470+
V: IntoLua + 'static;
471471

472472
/// Add a regular field getter as a method which accepts a `&T` as the parameter.
473473
///
@@ -528,7 +528,7 @@ pub trait UserDataFields<T> {
528528
/// like `__gc` or `__metatable`.
529529
fn add_meta_field<V>(&mut self, name: impl ToString, value: V)
530530
where
531-
V: IntoLua + Clone + 'static;
531+
V: IntoLua + 'static;
532532

533533
/// Add a metatable field computed from `f`.
534534
///
@@ -540,7 +540,7 @@ pub trait UserDataFields<T> {
540540
/// like `__gc` or `__metatable`.
541541
fn add_meta_field_with<F, R>(&mut self, name: impl ToString, f: F)
542542
where
543-
F: Fn(&Lua) -> Result<R> + MaybeSend + 'static,
543+
F: FnOnce(&Lua) -> Result<R> + 'static,
544544
R: IntoLua;
545545
}
546546

src/userdata/registry.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::os::raw::c_int;
77
use std::string::String as StdString;
88

99
use crate::error::{Error, Result};
10-
use crate::state::Lua;
10+
use crate::state::{Lua, RawLua};
1111
use crate::types::{Callback, MaybeSend};
1212
use crate::userdata::{
1313
AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, UserDataRefMut,
@@ -23,13 +23,15 @@ use {
2323
std::future::{self, Future},
2424
};
2525

26+
type StaticFieldCallback = Box<dyn FnOnce(&RawLua) -> Result<()> + 'static>;
27+
2628
/// Handle to registry for userdata methods and metamethods.
2729
pub struct UserDataRegistry<T: 'static> {
2830
// Fields
29-
pub(crate) fields: Vec<(String, Callback)>,
31+
pub(crate) fields: Vec<(String, StaticFieldCallback)>,
3032
pub(crate) field_getters: Vec<(String, Callback)>,
3133
pub(crate) field_setters: Vec<(String, Callback)>,
32-
pub(crate) meta_fields: Vec<(String, Callback)>,
34+
pub(crate) meta_fields: Vec<(String, StaticFieldCallback)>,
3335

3436
// Methods
3537
pub(crate) methods: Vec<(String, Callback)>,
@@ -283,11 +285,13 @@ fn get_function_name<T>(name: &str) -> StdString {
283285
impl<T: 'static> UserDataFields<T> for UserDataRegistry<T> {
284286
fn add_field<V>(&mut self, name: impl ToString, value: V)
285287
where
286-
V: IntoLua + Clone + 'static,
288+
V: IntoLua + 'static,
287289
{
288290
let name = name.to_string();
289-
let callback: Callback = Box::new(move |lua, _| unsafe { value.clone().push_into_stack_multi(lua) });
290-
self.fields.push((name, callback));
291+
self.fields.push((
292+
name,
293+
Box::new(move |rawlua| unsafe { value.push_into_stack(rawlua) }),
294+
));
291295
}
292296

293297
fn add_field_method_get<M, R>(&mut self, name: impl ToString, method: M)
@@ -332,28 +336,28 @@ impl<T: 'static> UserDataFields<T> for UserDataRegistry<T> {
332336

333337
fn add_meta_field<V>(&mut self, name: impl ToString, value: V)
334338
where
335-
V: IntoLua + Clone + 'static,
339+
V: IntoLua + 'static,
336340
{
337341
let name = name.to_string();
338342
self.meta_fields.push((
339343
name.clone(),
340-
Box::new(move |lua, _| unsafe {
341-
Self::check_meta_field(lua.lua(), &name, value.clone())?.push_into_stack_multi(lua)
344+
Box::new(move |rawlua| unsafe {
345+
Self::check_meta_field(rawlua.lua(), &name, value)?.push_into_stack(rawlua)
342346
}),
343347
));
344348
}
345349

346350
fn add_meta_field_with<F, R>(&mut self, name: impl ToString, f: F)
347351
where
348-
F: Fn(&Lua) -> Result<R> + MaybeSend + 'static,
352+
F: FnOnce(&Lua) -> Result<R> + 'static,
349353
R: IntoLua,
350354
{
351355
let name = name.to_string();
352356
self.meta_fields.push((
353357
name.clone(),
354-
Box::new(move |rawlua, _| unsafe {
358+
Box::new(move |rawlua| unsafe {
355359
let lua = rawlua.lua();
356-
Self::check_meta_field(lua, &name, f(lua)?)?.push_into_stack_multi(rawlua)
360+
Self::check_meta_field(lua, &name, f(lua)?)?.push_into_stack(rawlua)
357361
}),
358362
));
359363
}

0 commit comments

Comments
 (0)