use core::ptr::{self, NonNull};
use crate::Table;
use crate::function::{Closure, RawUpVal, UpVal};
use crate::gc::{GcObject, RawGcObject};
use crate::handle::RawHandle;
use crate::handle::sealed::Sealed;
use crate::string::{RawTString, TString};
use crate::table::RawLuaTable;
use crate::thread::Thread;
use crate::value::{RawTValue, TValueCursor};
use super::{CallInfo, CallInfoCursor, RawCallInfo, RawGlobalState};
#[repr(C)]
pub struct RawLuaState {
pub tt: u8,
pub marked: u8,
pub memcat: u8,
pub status: u8,
pub active_memcat: u8,
pub is_active: bool,
pub single_step: bool,
pub top: *mut RawTValue,
pub base: *mut RawTValue,
pub global: *mut RawGlobalState,
pub ci: *mut RawCallInfo,
pub stack_last: *mut RawTValue,
pub stack: *mut RawTValue,
pub end_ci: *mut RawCallInfo,
pub base_ci: *mut RawCallInfo,
pub stack_size: i32,
pub size_ci: i32,
pub native_call_depth: u16,
pub base_native_call_depth: u16,
pub cached_slot: i32,
pub gt: *mut RawLuaTable,
pub open_upval: *mut RawUpVal,
pub gc_list: *mut RawGcObject,
pub name_call: *mut RawTString,
pub userdata: *mut (),
}
#[allow(
clippy::missing_safety_doc,
reason = "all methods share the capability-level safety contract"
)]
pub trait ThreadState: Sealed + RawHandle<Raw = RawLuaState> {
unsafe fn from_raw(raw: NonNull<RawLuaState>) -> Self
where
Self: Sized;
unsafe fn current_call_info_cursor(&self) -> CallInfoCursor;
unsafe fn base_call_info_cursor(&self) -> CallInfoCursor;
unsafe fn current_call_info(&self) -> CallInfo {
unsafe { self.current_call_info_cursor().call_info_unchecked() }
}
unsafe fn base_call_info(&self) -> CallInfo {
unsafe { self.base_call_info_cursor().call_info_unchecked() }
}
unsafe fn set_current_call_info(&self, call_info: CallInfoCursor);
unsafe fn stack(&self) -> TValueCursor;
unsafe fn stack_base(&self) -> TValueCursor;
unsafe fn stack_top(&self) -> TValueCursor;
unsafe fn stack_last(&self) -> TValueCursor;
unsafe fn set_stack(&self, stack: TValueCursor);
unsafe fn set_stack_base(&self, base: TValueCursor);
unsafe fn set_stack_top(&self, top: TValueCursor);
unsafe fn open_upvalue(&self) -> Option<UpVal>;
unsafe fn set_open_upvalue(&self, upvalue: Option<UpVal>);
unsafe fn gc_list(&self) -> Option<GcObject>;
unsafe fn set_gc_list(&self, gc_list: Option<GcObject>);
unsafe fn name_call(&self) -> Option<TString>;
unsafe fn set_name_call(&self, name_call: Option<TString>);
unsafe fn cached_slot(&self) -> i32;
unsafe fn set_cached_slot(&self, cached_slot: i32);
unsafe fn restore_call_frame(&self, call_info: CallInfoCursor, top: TValueCursor) {
unsafe {
self.set_current_call_info(call_info);
self.set_stack_base(call_info.call_info_unchecked().base());
self.set_stack_top(top);
}
}
unsafe fn globals(&self) -> Table;
unsafe fn set_globals(&self, globals: Table);
unsafe fn increment_native_call_depth(&self);
unsafe fn decrement_native_call_depth(&self);
unsafe fn increment_base_native_call_depth(&self);
unsafe fn decrement_base_native_call_depth(&self);
unsafe fn current_function(&self) -> Closure {
unsafe { self.current_call_info().function_closure() }
}
unsafe fn current_env(&self) -> Table {
unsafe {
if self.current_call_info() == self.base_call_info() {
self.globals()
} else {
self.current_function().env()
}
}
}
}
impl ThreadState for Thread {
unsafe fn from_raw(raw: NonNull<RawLuaState>) -> Self {
Self { raw }
}
unsafe fn current_call_info_cursor(&self) -> CallInfoCursor {
unsafe { CallInfoCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().ci) }
}
unsafe fn base_call_info_cursor(&self) -> CallInfoCursor {
unsafe { CallInfoCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().base_ci) }
}
unsafe fn set_current_call_info(&self, call_info: CallInfoCursor) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().ci = call_info.as_ptr();
}
}
unsafe fn stack(&self) -> TValueCursor {
unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().stack) }
}
unsafe fn stack_base(&self) -> TValueCursor {
unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().base) }
}
unsafe fn stack_top(&self) -> TValueCursor {
unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().top) }
}
unsafe fn stack_last(&self) -> TValueCursor {
unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().stack_last) }
}
unsafe fn set_stack(&self, stack: TValueCursor) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().stack = stack.as_ptr();
}
}
unsafe fn set_stack_base(&self, base: TValueCursor) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().base = base.as_ptr();
}
}
unsafe fn set_stack_top(&self, top: TValueCursor) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().top = top.as_ptr();
}
}
unsafe fn open_upvalue(&self) -> Option<UpVal> {
unsafe {
NonNull::new(self.as_ptr().as_ref().unwrap_unchecked().open_upval)
.map(|upvalue| UpVal::from_raw(upvalue))
}
}
unsafe fn set_open_upvalue(&self, upvalue: Option<UpVal>) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().open_upval =
upvalue.map_or(ptr::null_mut(), |upvalue| upvalue.as_ptr());
}
}
unsafe fn gc_list(&self) -> Option<GcObject> {
unsafe {
NonNull::new(self.as_ptr().as_ref().unwrap_unchecked().gc_list)
.map(|raw| GcObject::from_raw(raw))
}
}
unsafe fn set_gc_list(&self, gc_list: Option<GcObject>) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().gc_list =
gc_list.map_or(ptr::null_mut(), |object| object.as_ptr());
}
}
unsafe fn name_call(&self) -> Option<TString> {
unsafe {
NonNull::new(self.as_ptr().as_ref().unwrap_unchecked().name_call)
.map(|raw| TString::from_raw(raw))
}
}
unsafe fn set_name_call(&self, name_call: Option<TString>) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().name_call =
name_call.map_or(ptr::null_mut(), |name_call| name_call.as_ptr());
}
}
unsafe fn cached_slot(&self) -> i32 {
unsafe { self.as_ptr().as_ref().unwrap_unchecked().cached_slot }
}
unsafe fn set_cached_slot(&self, cached_slot: i32) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().cached_slot = cached_slot;
}
}
unsafe fn globals(&self) -> Table {
unsafe {
debug_assert!(!self.as_ptr().as_ref().unwrap_unchecked().gt.is_null());
Table::from_raw(NonNull::new_unchecked(
self.as_ptr().as_ref().unwrap_unchecked().gt,
))
}
}
unsafe fn set_globals(&self, globals: Table) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().gt = globals.as_ptr();
}
}
unsafe fn increment_native_call_depth(&self) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().native_call_depth += 1;
}
}
unsafe fn decrement_native_call_depth(&self) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().native_call_depth -= 1;
}
}
unsafe fn increment_base_native_call_depth(&self) {
unsafe {
self.as_ptr()
.as_mut()
.unwrap_unchecked()
.base_native_call_depth += 1;
}
}
unsafe fn decrement_base_native_call_depth(&self) {
unsafe {
self.as_ptr()
.as_mut()
.unwrap_unchecked()
.base_native_call_depth -= 1;
}
}
}