use std::rc::Rc;
use luau_vm::lua::Lua as VmLua;
use luau_vm::state::{LuaAllocator, SystemLuaAllocator};
use crate::error::Error;
use crate::hooks::CallbackManager;
use crate::lua::runtime::RuntimeData;
use crate::thread::Thread;
use luau_vm::Thread as VmThread;
mod app_data;
mod chunk;
mod compiler;
mod debug;
mod gc;
mod memory;
mod reference;
mod registry;
pub(crate) mod runtime;
mod sandbox;
mod scope;
mod stdlib;
use memory::{MemoryState, TrackingAllocator};
pub(crate) use sandbox::ChunkLoad;
pub use app_data::{AppDataRef, AppDataRefMut};
pub use chunk::{AsChunk, Chunk, ChunkMode, SandboxedChunk};
#[cfg(feature = "macros")]
#[doc(hidden)]
pub use chunk::{CaptureEnvironment, CapturedChunk, captured_chunk};
pub use compiler::{CompileConstant, Compiler};
pub use debug::StackInfo;
pub use reference::LuaRef;
pub use registry::RegistryKey;
pub(crate) use registry::RegistryState;
pub use scope::Scope;
pub use stdlib::StdLib;
pub struct Lua {
state: VmLua,
pub(crate) runtime: Box<RuntimeData>,
}
impl Lua {
pub fn new() -> Result<Self, Error> {
Self::new_with_libs(StdLib::ALL)
}
pub fn new_with_libs(libs: StdLib) -> Result<Self, Error> {
luau_common::flags::initialize_luau_flags_default();
let memory = Rc::new(MemoryState::default());
let state = VmLua::new_with_allocator(TrackingAllocator::new(
SystemLuaAllocator,
Rc::clone(&memory),
))
.ok_or_else(|| Error::MemoryError("failed to allocate Luau state".to_string()))?;
let lua = Self::from_vm(state, memory);
lua.load_std_libs(libs)?;
Ok(lua)
}
pub fn new_with_allocator<A: LuaAllocator + 'static>(allocator: A) -> Result<Self, Error> {
Self::new_with(allocator, StdLib::ALL)
}
pub fn new_with<A: LuaAllocator + 'static>(allocator: A, libs: StdLib) -> Result<Self, Error> {
luau_common::flags::initialize_luau_flags_default();
let memory = Rc::new(MemoryState::default());
let state =
VmLua::new_with_allocator(TrackingAllocator::new(allocator, Rc::clone(&memory)))
.ok_or_else(|| Error::MemoryError("failed to allocate Luau state".to_string()))?;
let lua = Self::from_vm(state, memory);
lua.load_std_libs(libs)?;
Ok(lua)
}
fn from_vm(state: VmLua, memory: Rc<MemoryState>) -> Self {
let runtime = Box::new(RuntimeData::new(memory, state.main_thread()));
let mut lua = Self { state, runtime };
lua.install_runtime_data();
lua
}
pub fn current_thread(&self) -> Thread<'_> {
Thread::new(self.state.main_thread(), &self.runtime)
}
pub(crate) fn lua_ref(&self) -> LuaRef<'_> {
LuaRef::new(self.state.main_thread(), &self.runtime)
}
pub(crate) fn callback_parts(&mut self) -> (&VmThread, &mut CallbackManager) {
(self.state.main_thread(), self.runtime.callbacks_mut())
}
fn install_runtime_data(&mut self) {
unsafe {
self.runtime
.install_callbacks(&mut *self.state.main_thread().callbacks());
}
}
}
impl Drop for Lua {
fn drop(&mut self) {
self.runtime
.userdata_registrations()
.close(self.state.main_thread());
self.runtime.registry().close(self.state.main_thread());
}
}