luau 0.732.0

Safe lifetime-bound Rust embedding API for the Luau runtime
use luau_vm::Thread as VmThread;

use crate::error::Error;
use crate::thread::Thread;
use crate::value::{FromLua, IntoLua, LuaType, Value};

/// A light userdata value backed by an unmanaged raw pointer.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct LightUserdata {
    ptr: *mut (),
}

impl LightUserdata {
    /// A null light userdata value.
    pub const NULL: Self = Self {
        ptr: core::ptr::null_mut(),
    };

    /// Creates a null light userdata value.
    pub const fn null() -> Self {
        Self::NULL
    }

    /// Creates light userdata from an unmanaged pointer.
    pub const fn from_ptr(ptr: *mut ()) -> Self {
        Self { ptr }
    }

    /// Returns the stored pointer.
    pub const fn as_ptr(self) -> *mut () {
        self.ptr
    }

    /// Returns whether the stored pointer is null.
    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,
            )),
        }
    }
}