1use core::ptr::{self, NonNull};
2
3use crate::Table;
4use crate::function::{Closure, RawUpVal, UpVal};
5use crate::gc::{GcObject, RawGcObject};
6use crate::handle::RawHandle;
7use crate::handle::sealed::Sealed;
8use crate::string::{RawTString, TString};
9use crate::table::RawLuaTable;
10use crate::thread::Thread;
11use crate::value::{RawTValue, TValueCursor};
12
13use super::{CallInfo, CallInfoCursor, RawCallInfo, RawGlobalState};
14
15#[repr(C)]
16pub struct RawLuaState {
17 pub tt: u8,
18 pub marked: u8,
19 pub memcat: u8,
20 pub status: u8,
21 pub active_memcat: u8,
22 pub is_active: bool,
23 pub single_step: bool,
24 pub top: *mut RawTValue,
25 pub base: *mut RawTValue,
26 pub global: *mut RawGlobalState,
27 pub ci: *mut RawCallInfo,
28 pub stack_last: *mut RawTValue,
29 pub stack: *mut RawTValue,
30 pub end_ci: *mut RawCallInfo,
31 pub base_ci: *mut RawCallInfo,
32 pub stack_size: i32,
33 pub size_ci: i32,
34 pub native_call_depth: u16,
35 pub base_native_call_depth: u16,
36 pub cached_slot: i32,
37 pub gt: *mut RawLuaTable,
38 pub open_upval: *mut RawUpVal,
39 pub gc_list: *mut RawGcObject,
40 pub name_call: *mut RawTString,
41 pub userdata: *mut (),
42}
43
44#[allow(
52 clippy::missing_safety_doc,
53 reason = "all methods share the capability-level safety contract"
54)]
55pub trait ThreadState: Sealed + RawHandle<Raw = RawLuaState> {
56 unsafe fn from_raw(raw: NonNull<RawLuaState>) -> Self
57 where
58 Self: Sized;
59
60 unsafe fn current_call_info_cursor(&self) -> CallInfoCursor;
61
62 unsafe fn base_call_info_cursor(&self) -> CallInfoCursor;
63
64 unsafe fn current_call_info(&self) -> CallInfo {
65 unsafe { self.current_call_info_cursor().call_info_unchecked() }
66 }
67
68 unsafe fn base_call_info(&self) -> CallInfo {
69 unsafe { self.base_call_info_cursor().call_info_unchecked() }
70 }
71
72 unsafe fn set_current_call_info(&self, call_info: CallInfoCursor);
73
74 unsafe fn stack(&self) -> TValueCursor;
75
76 unsafe fn stack_base(&self) -> TValueCursor;
77
78 unsafe fn stack_top(&self) -> TValueCursor;
79
80 unsafe fn stack_last(&self) -> TValueCursor;
81
82 unsafe fn set_stack(&self, stack: TValueCursor);
83
84 unsafe fn set_stack_base(&self, base: TValueCursor);
85
86 unsafe fn set_stack_top(&self, top: TValueCursor);
87
88 unsafe fn open_upvalue(&self) -> Option<UpVal>;
89
90 unsafe fn set_open_upvalue(&self, upvalue: Option<UpVal>);
91
92 unsafe fn gc_list(&self) -> Option<GcObject>;
93
94 unsafe fn set_gc_list(&self, gc_list: Option<GcObject>);
95
96 unsafe fn name_call(&self) -> Option<TString>;
97
98 unsafe fn set_name_call(&self, name_call: Option<TString>);
99
100 unsafe fn cached_slot(&self) -> i32;
101
102 unsafe fn set_cached_slot(&self, cached_slot: i32);
103
104 unsafe fn restore_call_frame(&self, call_info: CallInfoCursor, top: TValueCursor) {
105 unsafe {
106 self.set_current_call_info(call_info);
107 self.set_stack_base(call_info.call_info_unchecked().base());
108 self.set_stack_top(top);
109 }
110 }
111
112 unsafe fn globals(&self) -> Table;
113
114 unsafe fn set_globals(&self, globals: Table);
115
116 unsafe fn increment_native_call_depth(&self);
117
118 unsafe fn decrement_native_call_depth(&self);
119
120 unsafe fn increment_base_native_call_depth(&self);
121
122 unsafe fn decrement_base_native_call_depth(&self);
123
124 unsafe fn current_function(&self) -> Closure {
125 unsafe { self.current_call_info().function_closure() }
126 }
127
128 unsafe fn current_env(&self) -> Table {
129 unsafe {
130 if self.current_call_info() == self.base_call_info() {
131 self.globals()
132 } else {
133 self.current_function().env()
134 }
135 }
136 }
137}
138
139impl ThreadState for Thread {
140 unsafe fn from_raw(raw: NonNull<RawLuaState>) -> Self {
141 Self { raw }
142 }
143
144 unsafe fn current_call_info_cursor(&self) -> CallInfoCursor {
145 unsafe { CallInfoCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().ci) }
146 }
147
148 unsafe fn base_call_info_cursor(&self) -> CallInfoCursor {
149 unsafe { CallInfoCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().base_ci) }
150 }
151
152 unsafe fn set_current_call_info(&self, call_info: CallInfoCursor) {
153 unsafe {
154 self.as_ptr().as_mut().unwrap_unchecked().ci = call_info.as_ptr();
155 }
156 }
157
158 unsafe fn stack(&self) -> TValueCursor {
159 unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().stack) }
160 }
161
162 unsafe fn stack_base(&self) -> TValueCursor {
163 unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().base) }
164 }
165
166 unsafe fn stack_top(&self) -> TValueCursor {
167 unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().top) }
168 }
169
170 unsafe fn stack_last(&self) -> TValueCursor {
171 unsafe { TValueCursor::from_ptr(self.as_ptr().as_ref().unwrap_unchecked().stack_last) }
172 }
173
174 unsafe fn set_stack(&self, stack: TValueCursor) {
175 unsafe {
176 self.as_ptr().as_mut().unwrap_unchecked().stack = stack.as_ptr();
177 }
178 }
179
180 unsafe fn set_stack_base(&self, base: TValueCursor) {
181 unsafe {
182 self.as_ptr().as_mut().unwrap_unchecked().base = base.as_ptr();
183 }
184 }
185
186 unsafe fn set_stack_top(&self, top: TValueCursor) {
187 unsafe {
188 self.as_ptr().as_mut().unwrap_unchecked().top = top.as_ptr();
189 }
190 }
191
192 unsafe fn open_upvalue(&self) -> Option<UpVal> {
193 unsafe {
194 NonNull::new(self.as_ptr().as_ref().unwrap_unchecked().open_upval)
195 .map(|upvalue| UpVal::from_raw(upvalue))
196 }
197 }
198
199 unsafe fn set_open_upvalue(&self, upvalue: Option<UpVal>) {
200 unsafe {
201 self.as_ptr().as_mut().unwrap_unchecked().open_upval =
202 upvalue.map_or(ptr::null_mut(), |upvalue| upvalue.as_ptr());
203 }
204 }
205
206 unsafe fn gc_list(&self) -> Option<GcObject> {
207 unsafe {
208 NonNull::new(self.as_ptr().as_ref().unwrap_unchecked().gc_list)
209 .map(|raw| GcObject::from_raw(raw))
210 }
211 }
212
213 unsafe fn set_gc_list(&self, gc_list: Option<GcObject>) {
214 unsafe {
215 self.as_ptr().as_mut().unwrap_unchecked().gc_list =
216 gc_list.map_or(ptr::null_mut(), |object| object.as_ptr());
217 }
218 }
219
220 unsafe fn name_call(&self) -> Option<TString> {
221 unsafe {
222 NonNull::new(self.as_ptr().as_ref().unwrap_unchecked().name_call)
223 .map(|raw| TString::from_raw(raw))
224 }
225 }
226
227 unsafe fn set_name_call(&self, name_call: Option<TString>) {
228 unsafe {
229 self.as_ptr().as_mut().unwrap_unchecked().name_call =
230 name_call.map_or(ptr::null_mut(), |name_call| name_call.as_ptr());
231 }
232 }
233
234 unsafe fn cached_slot(&self) -> i32 {
235 unsafe { self.as_ptr().as_ref().unwrap_unchecked().cached_slot }
236 }
237
238 unsafe fn set_cached_slot(&self, cached_slot: i32) {
239 unsafe {
240 self.as_ptr().as_mut().unwrap_unchecked().cached_slot = cached_slot;
241 }
242 }
243
244 unsafe fn globals(&self) -> Table {
245 unsafe {
246 debug_assert!(!self.as_ptr().as_ref().unwrap_unchecked().gt.is_null());
247 Table::from_raw(NonNull::new_unchecked(
248 self.as_ptr().as_ref().unwrap_unchecked().gt,
249 ))
250 }
251 }
252
253 unsafe fn set_globals(&self, globals: Table) {
254 unsafe {
255 self.as_ptr().as_mut().unwrap_unchecked().gt = globals.as_ptr();
256 }
257 }
258
259 unsafe fn increment_native_call_depth(&self) {
260 unsafe {
261 self.as_ptr().as_mut().unwrap_unchecked().native_call_depth += 1;
262 }
263 }
264
265 unsafe fn decrement_native_call_depth(&self) {
266 unsafe {
267 self.as_ptr().as_mut().unwrap_unchecked().native_call_depth -= 1;
268 }
269 }
270
271 unsafe fn increment_base_native_call_depth(&self) {
272 unsafe {
273 self.as_ptr()
274 .as_mut()
275 .unwrap_unchecked()
276 .base_native_call_depth += 1;
277 }
278 }
279
280 unsafe fn decrement_base_native_call_depth(&self) {
281 unsafe {
282 self.as_ptr()
283 .as_mut()
284 .unwrap_unchecked()
285 .base_native_call_depth -= 1;
286 }
287 }
288}