luau 0.732.0

Safe lifetime-bound Rust embedding API for the Luau runtime
use luau_vm::thread::StackGuard;
use luau_vm::{LUA_GC_COLLECT, LUA_GC_IS_RUNNING, LUA_GC_RESTART, LUA_GC_STEP, LUA_GC_STOP};

use super::{Lua, LuaRef};
use crate::Error;

impl Lua {
    /// Returns whether automatic garbage collection is enabled.
    pub fn gc_is_running(&self) -> Result<bool, Error> {
        self.lua_ref().gc_is_running()
    }

    /// Stops automatic garbage collection.
    pub fn gc_stop(&self) -> Result<(), Error> {
        self.lua_ref().gc_stop()
    }

    /// Restarts automatic garbage collection.
    pub fn gc_restart(&self) -> Result<(), Error> {
        self.lua_ref().gc_restart()
    }

    /// Performs a full garbage-collection cycle.
    ///
    /// Collecting every currently unreachable object can require two cycles:
    /// one to finish the active cycle and another to complete the next one.
    pub fn gc_collect(&self) -> Result<(), Error> {
        self.lua_ref().gc_collect()
    }

    /// Performs one incremental collection step.
    ///
    /// Returns `true` when the step completes a collection cycle.
    pub fn gc_step(&self) -> Result<bool, Error> {
        self.lua_ref().gc_step()
    }
}

impl LuaRef<'_> {
    /// Returns whether automatic garbage collection is enabled.
    pub fn gc_is_running(&self) -> Result<bool, Error> {
        let thread = self.as_vm();
        unsafe {
            thread
                .gc(LUA_GC_IS_RUNNING, 0)
                .map(|running| running != 0)
                .map_err(|error| Error::from_thread_exit(thread, error))
        }
    }

    /// Stops automatic garbage collection.
    pub fn gc_stop(&self) -> Result<(), Error> {
        let thread = self.as_vm();
        unsafe {
            thread
                .gc(LUA_GC_STOP, 0)
                .map(drop)
                .map_err(|error| Error::from_thread_exit(thread, error))
        }
    }

    /// Restarts automatic garbage collection.
    pub fn gc_restart(&self) -> Result<(), Error> {
        let thread = self.as_vm();
        unsafe {
            thread
                .gc(LUA_GC_RESTART, 0)
                .map(drop)
                .map_err(|error| Error::from_thread_exit(thread, error))
        }
    }

    /// Performs a full garbage-collection cycle.
    ///
    /// Collecting every currently unreachable object can require two cycles:
    /// one to finish the active cycle and another to complete the next one.
    pub fn gc_collect(&self) -> Result<(), Error> {
        let thread = self.as_vm();
        unsafe {
            let _stack = StackGuard::new(thread);
            thread
                .gc(LUA_GC_COLLECT, 0)
                .map(|_| ())
                .map_err(|error| Error::from_thread_exit(thread, error))
        }
    }

    /// Performs one incremental collection step.
    ///
    /// Returns `true` when the step completes a collection cycle.
    pub fn gc_step(&self) -> Result<bool, Error> {
        let thread = self.as_vm();
        unsafe {
            let _stack = StackGuard::new(thread);
            thread
                .gc(LUA_GC_STEP, 0)
                .map(|finished| finished != 0)
                .map_err(|error| Error::from_thread_exit(thread, error))
        }
    }
}