use std::marker::PhantomData;
use mlua::{AnyUserData, Error, IntoLua, Lua, UserData};
use crate::{EnumGenerator, RecordGenerator, ToTypename, Type, TypeBody, TypeName};
pub trait StaticUserdata: UserData + 'static {}
impl<T: UserData + 'static> StaticUserdata for T {}
pub struct UserDataProxy<'lua, T: StaticUserdata> {
user_data: AnyUserData<'lua>,
ph_: PhantomData<T>,
}
impl<'lua, T: StaticUserdata> UserDataProxy<'lua, T> {
pub fn new(lua: &'lua Lua) -> Result<Self, Error> {
Ok(Self {
user_data: lua.create_proxy::<T>()?,
ph_: Default::default(),
})
}
}
impl<T: StaticUserdata + ToTypename> ToTypename for UserDataProxy<'_, T> {
fn to_typename() -> crate::Type {
let mut x = T::to_typename();
if let Type::Single(x) = &mut x {
x.name = format!("Class{}", x.name).into();
}
x
}
}
impl<T: StaticUserdata + TypeBody + ToTypename> TypeBody for UserDataProxy<'_, T> {
fn get_type_body() -> crate::TypeGenerator {
let generator = T::get_type_body();
let type_name = Self::get_type_parts();
let type_name_string = type_name[..type_name.len() - 1]
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join("");
match generator {
crate::TypeGenerator::Record(record_generator) => {
crate::TypeGenerator::Record(Box::new(RecordGenerator {
type_name,
type_doc: format!("Collection of static methods for [`{}`].", type_name_string),
fields: Default::default(),
methods: Default::default(),
mut_methods: Default::default(),
meta_method: Default::default(),
meta_method_mut: Default::default(),
..record_generator.as_ref().clone()
}))
}
crate::TypeGenerator::Enum(enum_generator) => {
crate::TypeGenerator::Enum(EnumGenerator {
name: Self::get_type_parts(),
..enum_generator
})
}
}
}
}
impl<'lua, T: StaticUserdata> IntoLua<'lua> for UserDataProxy<'lua, T> {
fn into_lua(self, lua: &'lua Lua) -> mlua::Result<mlua::Value<'lua>> {
self.user_data.into_lua(lua)
}
}