Implement lua types for usize, make userdata field setter and getters return results
ci/woodpecker/push/debug Pipeline was successful Details

This commit is contained in:
SeanOMik 2024-02-19 17:57:19 -05:00
parent 9b542fb523
commit d32c138e99
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
4 changed files with 104 additions and 57 deletions

View File

@ -107,6 +107,7 @@ impl_as_lua_number!(u8);
impl_as_lua_number!(u16); impl_as_lua_number!(u16);
impl_as_lua_number!(u32); impl_as_lua_number!(u32);
impl_as_lua_number!(u64); impl_as_lua_number!(u64);
impl_as_lua_number!(usize);
impl_as_lua_number!(f32); impl_as_lua_number!(f32);
impl_as_lua_number!(f64); impl_as_lua_number!(f64);
@ -142,3 +143,28 @@ impl<'a> PushToLuaStack<'a> for &str {
Ok(()) Ok(())
} }
} }
impl<'a> AsLua<'a> for bool {
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
Ok(Value::Boolean(self))
}
}
impl<'a> FromLua<'a> for bool {
fn from_lua(_lua: &State, val: Value) -> crate::Result<Self> {
match val {
Value::Boolean(v) => Ok(v),
_ => Err(Error::type_mismatch(
"Boolean",
&val.type_name(),
)),
}
}
}
impl<'a> PushToLuaStack<'a> for bool {
unsafe fn push_to_lua_stack(&self, state: &'a State) -> crate::Result<()> {
let v = self.as_lua(state)?;
v.push_to_lua_stack(state)
}
}

View File

@ -10,10 +10,16 @@ pub struct Vec2 {
impl Userdata for Vec2 { impl Userdata for Vec2 {
fn build<'a>(_state: &State, builder: &mut UserdataBuilder<'a, Vec2>) -> crate::Result<()> { fn build<'a>(_state: &State, builder: &mut UserdataBuilder<'a, Vec2>) -> crate::Result<()> {
builder builder
.field_getter("x", |_, this| this.x) .field_getter("x", |_, this| Ok(this.x))
.field_getter("y", |_, this| this.y) .field_getter("y", |_, this| Ok(this.y))
.field_setter("x", |_, this, x: f32| this.x = x) .field_setter("x", |_, this, x: f32| {
.field_setter("y", |_, this, y: f32| this.y = y) this.x = x;
Ok(())
})
.field_setter("y", |_, this, y: f32| {
this.y = y;
Ok(())
})
.function("new", |lua, (x, y)| lua.create_userdata(Vec2 { x, y })) .function("new", |lua, (x, y)| lua.create_userdata(Vec2 { x, y }))
// method test // method test
.method("add", |lua, lhs: &Vec2, (rhs,): (Ref<Vec2>,)| { .method("add", |lua, lhs: &Vec2, (rhs,): (Ref<Vec2>,)| {

View File

@ -8,6 +8,7 @@ pub type UserdataMutGetterFn<'a> = Arc<OnceCell<Box<dyn Fn(AnyUserdata<'a>) -> c
pub struct UserdataBuilder<'a, T> { pub struct UserdataBuilder<'a, T> {
pub(crate) name: String, pub(crate) name: String,
pub(crate) field_consts: HashMap<String, UserdataFn<'a>>,
pub(crate) field_getters: HashMap<String, UserdataFn<'a>>, pub(crate) field_getters: HashMap<String, UserdataFn<'a>>,
pub(crate) field_setters: HashMap<String, UserdataFn<'a>>, pub(crate) field_setters: HashMap<String, UserdataFn<'a>>,
pub(crate) functions: HashMap<String, UserdataFn<'a>>, pub(crate) functions: HashMap<String, UserdataFn<'a>>,
@ -23,6 +24,7 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
name: T::name(), name: T::name(),
field_consts: HashMap::new(),
field_getters: HashMap::new(), field_getters: HashMap::new(),
field_setters: HashMap::new(), field_setters: HashMap::new(),
functions: HashMap::new(), functions: HashMap::new(),
@ -33,13 +35,14 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> {
} }
} }
pub fn field_getter<F, R>(&mut self, name: &str, f: F) -> &mut Self pub fn field<R>(&mut self, name: &str, f: R) -> &mut Self
where where
F: Fn(&'a State, &T) -> R + 'static, //F: Fn(&'a State) -> R + 'static,
R: AsLua<'a>, R: AsLua<'a>,
T: Userdata + 'static //T: Userdata + 'static
{ {
let wrapped = self.wrapped_getter.clone(); todo!()
/* let wrapped = self.wrapped_getter.clone();
let wrapped: Arc<OnceCell<Box<dyn Fn(AnyUserdata<'_>) -> Result<*const (), crate::Error>>>> = unsafe { mem::transmute(wrapped) }; let wrapped: Arc<OnceCell<Box<dyn Fn(AnyUserdata<'_>) -> Result<*const (), crate::Error>>>> = unsafe { mem::transmute(wrapped) };
let ud_name = self.name.clone(); let ud_name = self.name.clone();
@ -68,12 +71,50 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> {
}; };
self.field_getters.insert(name.to_string(), Box::new(wrap)); self.field_getters.insert(name.to_string(), Box::new(wrap));
self */
}
pub fn field_getter<F, R>(&mut self, name: &str, f: F) -> &mut Self
where
F: Fn(&'a State, &T) -> crate::Result<R> + 'static,
R: AsLua<'a>,
T: Userdata + 'static
{
let wrapped = self.wrapped_getter.clone();
let wrapped: Arc<OnceCell<Box<dyn Fn(AnyUserdata<'_>) -> Result<*const (), crate::Error>>>> = unsafe { mem::transmute(wrapped) };
let ud_name = self.name.clone();
let fn_name = name.to_string();
let wrap = move |lua: &'a State, mut val: ValueVec<'a>| {
let val = val.pop_front().unwrap();
let this = val.as_userdata().unwrap(); // if this panics, its a bug
if let Some(getter) = wrapped.get() {
let this_ptr = Self::result_to_bad_arg(
getter(this.clone()),
&ud_name,
&fn_name,
1,
Some("self")
)?;
let this_ptr = this_ptr.cast::<T>();
let this = unsafe { &*this_ptr };
f(lua, this)?.as_lua(lua)
} else {
let this = this.as_ref::<T>()?;
f(lua, &*this)?.as_lua(lua)
}
};
self.field_getters.insert(name.to_string(), Box::new(wrap));
self self
} }
pub fn field_setter<F, V>(&mut self, name: &str, f: F) -> &mut Self pub fn field_setter<F, V>(&mut self, name: &str, f: F) -> &mut Self
where where
F: Fn(&'a State, &mut T, V) -> () + 'static, F: Fn(&'a State, &mut T, V) -> crate::Result<()> + 'static,
V: FromLua<'a>, V: FromLua<'a>,
T: Userdata + 'static T: Userdata + 'static
{ {
@ -101,11 +142,11 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> {
let this_ptr = this_ptr.cast::<T>(); let this_ptr = this_ptr.cast::<T>();
let this = unsafe { this_ptr.as_mut().unwrap() }; let this = unsafe { this_ptr.as_mut().unwrap() };
f(lua, this, v_arg).as_lua(lua) f(lua, this, v_arg)?.as_lua(lua)
} else { } else {
let mut this = this.as_mut::<T>()?; let mut this = this.as_mut::<T>()?;
f(lua, this.deref_mut(), v_arg).as_lua(lua) f(lua, this.deref_mut(), v_arg)?.as_lua(lua)
} }
}; };
self.field_setters.insert(name.to_string(), Box::new(wrap)); self.field_setters.insert(name.to_string(), Box::new(wrap));

View File

@ -417,23 +417,6 @@ impl<'a> IntoLuaVec<'a> for ValueVec<'a> {
} }
} }
/* impl<'a> FromLua<'a> for ValueVec<'a> {
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
match val {
Value::Variable(v) => Ok(v),
_ => {
Ok(ValueVec::from(val))
}
}
}
} */
/* impl<'a> FromLuaVec<'a> for ValueVec<'a> {
fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
Ok(values)
}
} */
impl<'a> PushToLuaStack<'a> for ValueVec<'a> { impl<'a> PushToLuaStack<'a> for ValueVec<'a> {
unsafe fn push_to_lua_stack(&self, state: &'a State) -> crate::Result<()> { unsafe fn push_to_lua_stack(&self, state: &'a State) -> crate::Result<()> {
for v in self.iter() { for v in self.iter() {
@ -465,13 +448,6 @@ macro_rules! impl_from_lua_vec_for_from_lua {
Some(1) Some(1)
} }
} }
/* impl<'a> IntoLuaVec<'a> for $type<'a> {
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
Ok(ValueVec::from(self.as_lua(state)?))
}
} */
}; };
($type: tt) => { ($type: tt) => {
impl<'a> FromLuaVec<'a> for $type { impl<'a> FromLuaVec<'a> for $type {
@ -490,16 +466,11 @@ macro_rules! impl_from_lua_vec_for_from_lua {
Some(1) Some(1)
} }
} }
/* impl<'a> IntoLuaVec<'a> for $type {
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
Ok(ValueVec::from(self.as_lua(state)?))
}
} */
}; };
} }
impl_from_lua_vec_for_from_lua!(i64); impl_from_lua_vec_for_from_lua!(i64);
impl_from_lua_vec_for_from_lua!(usize);
impl_from_lua_vec_for_from_lua!(u64); impl_from_lua_vec_for_from_lua!(u64);
impl_from_lua_vec_for_from_lua!(i16); impl_from_lua_vec_for_from_lua!(i16);
impl_from_lua_vec_for_from_lua!(u16); impl_from_lua_vec_for_from_lua!(u16);
@ -516,16 +487,6 @@ impl_from_lua_vec_for_from_lua!(Value, 'a);
impl_from_lua_vec_for_from_lua!(Function, 'a); impl_from_lua_vec_for_from_lua!(Function, 'a);
impl_from_lua_vec_for_from_lua!(AnyUserdata, 'a); impl_from_lua_vec_for_from_lua!(AnyUserdata, 'a);
/* impl<'a, T: FromLua<'a>> FromLuaVec<'a> for T {
fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result<Self> {
if let Some(v) = values.pop_front() {
Ok(T::from_lua(state, v)?)
} else {
Err(Error::Nil)
}
}
} */
impl<'a, T: AsLua<'a>> IntoLuaVec<'a> for T { impl<'a, T: AsLua<'a>> IntoLuaVec<'a> for T {
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> { fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
let mut v = ValueVec::new(); let mut v = ValueVec::new();
@ -607,12 +568,6 @@ impl<'a> FromLuaVec<'a> for () {
} }
} }
/* impl<'a> IntoLuaVec<'a> for () {
fn into_lua_value_vec(self, _state: &'a State) -> crate::Result<ValueVec<'a>> {
Ok(ValueVec::new())
}
} */
macro_rules! impl_from_lua_vec_tuple { macro_rules! impl_from_lua_vec_tuple {
( $count: expr, $last: tt, $( $name: tt ),+ ) => ( ( $count: expr, $last: tt, $( $name: tt ),+ ) => (
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -709,3 +664,22 @@ macro_rules! impl_from_lua_vec_tuple {
// hopefully 16 is more than enough // hopefully 16 is more than enough
// if you have 16 function results, and need more than 16, you NEED help // if you have 16 function results, and need more than 16, you NEED help
impl_from_lua_vec_tuple! { 16, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16 } impl_from_lua_vec_tuple! { 16, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16 }
impl<'a, T: AsLua<'a>, const N: usize> AsLua<'a> for [T; N] {
fn as_lua(self, lua: &'a State) -> crate::Result<Value<'a>> {
let table = lua.create_table()?;
for (idx, t) in self.into_iter().enumerate() {
table.set(idx + 1, t)?;
}
Ok(Value::Table(table))
}
}
// TODO: Find out a way to implement this
/* impl<'a, T: FromLua> FromLuaVec<'a> for T {
fn from_lua_value_vec(state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
todo!()
}
} */