lu 0.5.1

A library for embedding Luau
Documentation
use std::{cell::RefCell, marker::PhantomData, ops::Deref, ptr::NonNull};

use crate::{Config, Ref, Stack, Status};

#[repr(transparent)]
pub struct Thread<C: Config>(
    pub(crate) NonNull<sys::lua_State>,
    pub(crate) PhantomData<C>,
);

impl<C: Config> Thread<C> {
    pub fn as_ptr(&self) -> *mut sys::lua_State {
        self.0.as_ptr()
    }

    pub fn main(&self) -> ThreadMain<C> {
        let ptr = unsafe { NonNull::new_unchecked(sys::lua_mainthread(self.as_ptr())) };

        ThreadMain {
            thread: Thread(ptr, PhantomData),
        }
    }

    pub fn stack(&self) -> &Stack<C> {
        unsafe { std::mem::transmute(self) }
    }

    pub fn data(&self) -> &RefCell<C::ThreadData> {
        #[cfg(debug_assertions)]
        if self.main().as_ptr() == self.as_ptr() {
            panic!("cannot access thread data from the main thread");
        }

        unsafe {
            sys::lua_getthreaddata(self.as_ptr())
                .cast::<RefCell<C::ThreadData>>()
                .as_ref()
                .unwrap_unchecked()
        }
    }

    pub fn sandbox(&self) {
        unsafe { sys::luaL_sandboxthread(self.as_ptr()) }
    }

    pub fn resume(&self, from: Option<&Thread<C>>, nargs: u32) -> Status {
        let from = match from {
            Some(thread) => thread.as_ptr(),
            None => std::ptr::null_mut(),
        };

        unsafe { sys::lua_resume(self.as_ptr(), from, nargs as _) }.into()
    }
}

pub struct ThreadMain<C: Config> {
    pub(crate) thread: Thread<C>,
}

impl<C: Config> Deref for ThreadMain<C> {
    type Target = Thread<C>;

    fn deref(&self) -> &Self::Target {
        &self.thread
    }
}

impl<C: Config> ThreadMain<C> {
    pub fn data(&self) -> &RefCell<C::MainData> {
        unsafe {
            sys::lua_getthreaddata(self.as_ptr())
                .cast::<RefCell<C::MainData>>()
                .as_ref()
                .unwrap_unchecked()
        }
    }
}

pub struct ThreadRef<C: Config> {
    pub(crate) thread: Thread<C>,
    pub(crate) _thref: Ref<C>,
}

impl<C: Config> Deref for ThreadRef<C> {
    type Target = Thread<C>;

    fn deref(&self) -> &Self::Target {
        &self.thread
    }
}