use luau_vm::Thread as VmThread;
use crate::error::Error;
use crate::thread::Thread;
use crate::value::{FromLua, IntoLua, LuaType, Value};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct LightUserdata {
ptr: *mut (),
}
impl LightUserdata {
pub const NULL: Self = Self {
ptr: core::ptr::null_mut(),
};
pub const fn null() -> Self {
Self::NULL
}
pub const fn from_ptr(ptr: *mut ()) -> Self {
Self { ptr }
}
pub const fn as_ptr(self) -> *mut () {
self.ptr
}
pub const fn is_null(self) -> bool {
self.ptr.is_null()
}
}
impl LuaType for LightUserdata {
fn push_type_key(thread: impl AsRef<VmThread>) -> Result<(), Error> {
let thread = thread.as_ref();
unsafe {
thread
.push_light_userdata(Self::NULL.as_ptr())
.map_err(|exit| Error::from_thread_exit(thread, exit))
}
}
}
impl<'lua> IntoLua<'lua> for LightUserdata {
fn into_lua(self, _: crate::LuaRef<'lua>) -> Result<Value<'lua>, Error> {
Ok(Value::LightUserdata(self))
}
unsafe fn push_into_stack(self, thread: &Thread<'lua>) -> Result<(), Error> {
unsafe {
thread
.as_vm()
.push_light_userdata(self.as_ptr())
.map_err(|exit| Error::from_thread_exit(thread, exit))?;
}
Ok(())
}
}
impl<'lua> FromLua<'lua> for LightUserdata {
fn from_lua(value: Value<'lua>, _: crate::LuaRef<'lua>) -> Result<Self, Error> {
match value {
Value::LightUserdata(userdata) => Ok(userdata),
value => Err(Error::from_lua_conversion(
value.type_name(),
"lightuserdata",
None,
)),
}
}
}