Skip to main content

lua_stdlib/
state_stub.rs

1//! Phase-B reconcile shim: re-exports the canonical `LuaState` from
2//! `lua-vm` and provides an extension trait holding every method the
3//! Phase-A stdlib translation used to call on the Phase-A stub.
4//!
5//! TODO_ARCH(phase-b-reconcile): all extension-trait method bodies are
6//! `todo!("phase-b-reconcile: <name>")`. They must move to real
7//! implementations on `lua_vm::state::LuaState` itself; that work lives in
8//! `lua-vm`, not here. The shim exists only so stdlib code keeps compiling
9//! while the canonical `LuaState` API stabilises.
10//!
11//! Where a trait method's name collides with an inherent method on the
12//! canonical `LuaState`, Rust resolves to the inherent method. Most
13//! Phase-A call sites compile through the inherent method unchanged; the
14//! handful that depend on a different return shape (e.g. `state.push(...)?`
15//! against the canonical `pub fn push(&mut self, val: LuaValue)`) are
16//! patched at the call site.
17
18#![allow(dead_code, unused_variables, clippy::too_many_arguments)]
19
20use lua_types::{
21    arith::ArithOp,
22    closure::{LuaCFnPtr, LuaClosure},
23    error::LuaError,
24    gc::GcRef,
25    string::LuaString,
26    userdata::LuaUserData,
27    value::{LuaThread, LuaValue},
28    CallInfoIdx, LuaStatus, LuaType,
29};
30
31use lua_vm::state::LuaCallable;
32pub use lua_vm::state::LuaState;
33
34/// Bare function callable from Lua. C: `lua_CFunction`.
35#[allow(non_camel_case_types)]
36pub type lua_CFunction = fn(&mut LuaState) -> Result<usize, LuaError>;
37
38/// Pseudo-index for the `i`-th upvalue of a C function.
39pub fn upvalue_index(i: i32) -> i32 {
40    -1_001_000 - i
41}
42
43/// Comparison operations (eq, lt, le). C: `LUA_OP*`.
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum CompareOp {
46    Eq,
47    Lt,
48    Le,
49}
50
51/// Reader-callback type for `lua_load`. C: `lua_Reader`.
52pub type LuaReader<'a> = dyn FnMut() -> Option<Vec<u8>> + 'a;
53
54/// Writer-callback type for `lua_dump`. C: `lua_Writer`.
55pub type LuaWriter<'a> = dyn FnMut(&[u8]) -> Result<(), LuaError> + 'a;
56
57/// Debug introspection record. C: `lua_Debug`.
58#[derive(Debug, Default, Clone)]
59pub struct LuaDebug {
60    pub name: Option<Vec<u8>>,
61    pub namewhat: Vec<u8>,
62    pub what: u8,
63    pub source: Vec<u8>,
64    pub short_src: Vec<u8>,
65    pub linedefined: i32,
66    pub lastlinedefined: i32,
67    pub currentline: i32,
68    pub nups: u8,
69    pub nparams: u8,
70    pub isvararg: bool,
71    pub istailcall: bool,
72    pub extraargs: u8,
73    pub ftransfer: u16,
74    pub ntransfer: u16,
75    /// Active CallInfo index, set by `get_stack`/`get_stack_level` and read by
76    /// `get_info`/`get_local_at`/`set_local_at`. Mirrors C's `lua_Debug.i_ci`
77    /// (a raw pointer in C; an index here).
78    pub(crate) i_ci_idx: Option<CallInfoIdx>,
79}
80
81impl LuaDebug {
82    pub fn name_bytes(&self) -> &[u8] {
83        self.name.as_deref().unwrap_or(b"?")
84    }
85    pub fn namewhat_bytes(&self) -> &[u8] {
86        &self.namewhat
87    }
88    pub fn what_bytes(&self) -> &[u8] {
89        match self.what {
90            b'L' => b"Lua",
91            b'C' => b"C",
92            b'm' => b"main",
93            _ => b"?",
94        }
95    }
96    pub fn short_src_bytes(&self) -> &[u8] {
97        &self.short_src
98    }
99    pub fn source_bytes(&self) -> &[u8] {
100        &self.source
101    }
102}
103
104/// Extension trait wiring every Phase-A stub method onto the canonical
105/// `LuaState`. Bodies are `todo!("phase-b-reconcile: …")`. When the
106/// canonical type already defines a method with the same name, Rust's
107/// inherent-first resolution makes this trait method unreachable (the
108/// inherent one wins) — the trait is then only providing the *missing*
109/// methods. Conflicting call-sites whose shape no longer matches the
110/// inherent signature are patched in their respective stdlib modules.
111pub trait LuaStateStubExt {
112    fn push_value(&mut self, idx: i32) -> Result<(), LuaError> {
113        todo!("phase-b-reconcile: push_value")
114    }
115    fn push_copy(&mut self, idx: i32) -> Result<(), LuaError> {
116        todo!("phase-b-reconcile: push_copy")
117    }
118    fn push_string(&mut self, s: &[u8]) -> Result<(), LuaError> {
119        todo!("phase-b-reconcile: push_string")
120    }
121    fn push_bytes(&mut self, s: &[u8]) -> Result<(), LuaError> {
122        todo!("phase-b-reconcile: push_bytes")
123    }
124    fn push_fstring(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), LuaError> {
125        todo!("phase-b-reconcile: push_fstring")
126    }
127    fn push_c_function(&mut self, f: lua_CFunction) -> Result<(), LuaError> {
128        todo!("phase-b-reconcile: push_c_function")
129    }
130    fn push_c_closure(&mut self, f: lua_CFunction, n: i32) -> Result<(), LuaError> {
131        todo!("phase-b-reconcile: push_c_closure")
132    }
133    fn push_where(&mut self, level: i32) -> Result<(), LuaError> {
134        todo!("phase-b-reconcile: push_where")
135    }
136    fn push_globals(&mut self) -> Result<(), LuaError> {
137        todo!("phase-b-reconcile: push_globals")
138    }
139
140    fn pop_bytes(&mut self) -> Vec<u8> {
141        todo!("phase-b-reconcile: pop_bytes")
142    }
143
144    fn top(&mut self) -> i32 {
145        todo!("phase-b-reconcile: top")
146    }
147    fn top_count(&mut self) -> i32 {
148        todo!("phase-b-reconcile: top_count")
149    }
150
151    fn insert(&mut self, idx: i32) -> Result<(), LuaError> {
152        todo!("phase-b-reconcile: insert")
153    }
154    fn remove(&mut self, idx: i32) -> Result<(), LuaError> {
155        todo!("phase-b-reconcile: remove")
156    }
157    fn replace(&mut self, idx: i32) -> Result<(), LuaError> {
158        todo!("phase-b-reconcile: replace")
159    }
160    fn rotate(&mut self, idx: i32, n: i32) -> Result<(), LuaError> {
161        todo!("phase-b-reconcile: rotate")
162    }
163    fn copy_value(&mut self, from: i32, to: i32) -> Result<(), LuaError> {
164        todo!("phase-b-reconcile: copy_value")
165    }
166    fn abs_index(&mut self, idx: i32) -> i32 {
167        todo!("phase-b-reconcile: abs_index")
168    }
169    fn ensure_stack<S: AsRef<[u8]> + ?Sized>(&mut self, n: i32, msg: &S) -> Result<(), LuaError> {
170        let _ = msg.as_ref();
171        todo!("phase-b-reconcile: ensure_stack")
172    }
173    fn check_stack_space(&mut self, n: i32) -> bool {
174        todo!("phase-b-reconcile: check_stack_space")
175    }
176
177    fn type_at(&mut self, idx: i32) -> LuaType {
178        todo!("phase-b-reconcile: type_at")
179    }
180    fn type_name(&mut self, t: LuaType) -> &'static [u8] {
181        todo!("phase-b-reconcile: type_name")
182    }
183    fn type_name_at(&mut self, idx: i32) -> &'static [u8] {
184        todo!("phase-b-reconcile: type_name_at")
185    }
186    fn value_at(&mut self, idx: i32) -> LuaValue {
187        todo!("phase-b-reconcile: value_at")
188    }
189    fn is_none_or_nil(&mut self, idx: i32) -> bool {
190        todo!("phase-b-reconcile: is_none_or_nil")
191    }
192    fn is_integer(&mut self, idx: i32) -> bool {
193        todo!("phase-b-reconcile: is_integer")
194    }
195    fn is_number(&mut self, idx: i32) -> bool {
196        todo!("phase-b-reconcile: is_number")
197    }
198
199    fn to_lua_string(&mut self, idx: i32) -> Option<GcRef<LuaString>> {
200        todo!("phase-b-reconcile: to_lua_string")
201    }
202    fn to_lua_string_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
203        todo!("phase-b-reconcile: to_lua_string_bytes")
204    }
205    fn to_lua_string_len(&mut self, idx: i32) -> Option<usize> {
206        todo!("phase-b-reconcile: to_lua_string_len")
207    }
208    fn to_integer_x(&mut self, idx: i32) -> Option<i64> {
209        todo!("phase-b-reconcile: to_integer_x")
210    }
211    fn to_number_x(&mut self, idx: i32) -> Option<f64> {
212        todo!("phase-b-reconcile: to_number_x")
213    }
214    fn to_boolean(&mut self, idx: i32) -> bool {
215        todo!("phase-b-reconcile: to_boolean")
216    }
217    fn to_userdata(&mut self, idx: i32) -> Option<GcRef<LuaUserData>> {
218        todo!("phase-b-reconcile: to_userdata")
219    }
220    fn to_display_string(&mut self, idx: i32) -> Result<Vec<u8>, LuaError> {
221        todo!("phase-b-reconcile: to_display_string")
222    }
223
224    fn check_arg_any(&mut self, arg: i32) -> Result<(), LuaError> {
225        todo!("phase-b-reconcile: check_arg_any")
226    }
227    fn check_arg_integer(&mut self, arg: i32) -> Result<i64, LuaError> {
228        todo!("phase-b-reconcile: check_arg_integer")
229    }
230    fn check_arg_string(&mut self, arg: i32) -> Result<Vec<u8>, LuaError> {
231        todo!("phase-b-reconcile: check_arg_string")
232    }
233    fn check_arg_type(&mut self, arg: i32, t: LuaType) -> Result<(), LuaError> {
234        todo!("phase-b-reconcile: check_arg_type")
235    }
236    fn check_arg_option(
237        &mut self,
238        arg: i32,
239        def: Option<&[u8]>,
240        lst: &[&[u8]],
241    ) -> Result<usize, LuaError> {
242        todo!("phase-b-reconcile: check_arg_option")
243    }
244
245    fn opt_arg_integer(&mut self, arg: i32, def: i64) -> Result<i64, LuaError> {
246        todo!("phase-b-reconcile: opt_arg_integer")
247    }
248    fn opt_arg_string_bytes(&mut self, arg: i32) -> Result<Vec<u8>, LuaError> {
249        todo!("phase-b-reconcile: opt_arg_string_bytes")
250    }
251    fn opt_arg_string(&mut self, arg: i32, def: &[u8]) -> Result<Vec<u8>, LuaError> {
252        todo!("phase-b-reconcile: opt_arg_string")
253    }
254    fn arg_to_bool(&mut self, arg: i32) -> bool {
255        todo!("phase-b-reconcile: arg_to_bool")
256    }
257
258    fn get_field(&mut self, idx: i32, k: &[u8]) -> Result<LuaType, LuaError> {
259        todo!("phase-b-reconcile: get_field")
260    }
261    fn set_field(&mut self, idx: i32, k: &[u8]) -> Result<(), LuaError> {
262        todo!("phase-b-reconcile: set_field")
263    }
264    fn raw_get(&mut self, idx: i32) -> Result<LuaType, LuaError> {
265        todo!("phase-b-reconcile: raw_get")
266    }
267    fn raw_set(&mut self, idx: i32) -> Result<(), LuaError> {
268        todo!("phase-b-reconcile: raw_set")
269    }
270    fn raw_get_i(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
271        todo!("phase-b-reconcile: raw_get_i")
272    }
273    fn raw_set_i(&mut self, idx: i32, n: i64) -> Result<(), LuaError> {
274        todo!("phase-b-reconcile: raw_set_i")
275    }
276    fn raw_equal(&mut self, idx1: i32, idx2: i32) -> Result<bool, LuaError> {
277        todo!("phase-b-reconcile: raw_equal")
278    }
279    fn raw_len(&mut self, idx: i32) -> i64 {
280        todo!("phase-b-reconcile: raw_len")
281    }
282    fn get_i(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
283        todo!("phase-b-reconcile: get_i")
284    }
285    fn get_metafield(&mut self, idx: i32, name: &[u8]) -> Result<LuaType, LuaError> {
286        todo!("phase-b-reconcile: get_metafield")
287    }
288    fn get_meta_field(&mut self, idx: i32, name: &[u8]) -> Result<bool, LuaError> {
289        todo!("phase-b-reconcile: get_meta_field")
290    }
291    fn get_metatable(&mut self, idx: i32) -> Result<bool, LuaError> {
292        todo!("phase-b-reconcile: get_metatable")
293    }
294    fn set_metatable(&mut self, idx: i32) -> Result<(), LuaError> {
295        todo!("phase-b-reconcile: set_metatable")
296    }
297    fn table_next(&mut self, idx: i32) -> Result<bool, LuaError> {
298        todo!("phase-b-reconcile: table_next")
299    }
300    fn create_table(&mut self, narr: i32, nrec: i32) -> Result<(), LuaError> {
301        todo!("phase-b-reconcile: create_table")
302    }
303
304    fn gc_control_simple(&mut self, op: i32) -> Result<i32, LuaError> {
305        todo!("phase-b-reconcile: gc_control_simple")
306    }
307    fn gc_count(&mut self) -> Result<i32, LuaError> {
308        todo!("phase-b-reconcile: gc_count")
309    }
310    fn gc_count_b(&mut self) -> Result<i32, LuaError> {
311        todo!("phase-b-reconcile: gc_count_b")
312    }
313    fn gc_step(&mut self, data: i32) -> Result<i32, LuaError> {
314        todo!("phase-b-reconcile: gc_step")
315    }
316    fn gc_set_param(&mut self, op: i32, value: i32) -> Result<i32, LuaError> {
317        todo!("phase-b-reconcile: gc_set_param")
318    }
319    fn gc_is_running(&mut self) -> Result<bool, LuaError> {
320        todo!("phase-b-reconcile: gc_is_running")
321    }
322    fn gc_gen(&mut self, minor_mul: i32, major_mul: i32) -> Result<i32, LuaError> {
323        todo!("phase-b-reconcile: gc_gen")
324    }
325    fn gc_inc(&mut self, pause: i32, step_mul: i32, step_size: i32) -> Result<i32, LuaError> {
326        todo!("phase-b-reconcile: gc_inc")
327    }
328    fn gc_param(&mut self, param: usize, value: i64) -> Result<i64, LuaError> {
329        todo!("phase-b-reconcile: gc_param")
330    }
331
332    fn call(&mut self, nargs: i32, nresults: i32) -> Result<(), LuaError> {
333        todo!("phase-b-reconcile: call")
334    }
335    fn call_k(
336        &mut self,
337        nargs: i32,
338        nresults: i32,
339        ctx: isize,
340        k: Option<fn(&mut LuaState, i32, isize) -> Result<usize, LuaError>>,
341    ) -> Result<(), LuaError> {
342        let _ = (nargs, nresults, ctx, k);
343        todo!("phase-b-reconcile: call_k")
344    }
345    fn protected_call(&mut self, nargs: i32, nresults: i32, msgh: i32) -> Result<(), LuaError> {
346        todo!("phase-b-reconcile: protected_call")
347    }
348    fn protected_call_k(
349        &mut self,
350        nargs: i32,
351        nresults: i32,
352        msgh: i32,
353        ctx: isize,
354        k: Option<fn(&mut LuaState, i32, isize) -> Result<usize, LuaError>>,
355    ) -> Result<(), LuaError> {
356        let _ = (nargs, nresults, msgh, ctx, k);
357        todo!("phase-b-reconcile: protected_call_k")
358    }
359    fn len_op(&mut self, idx: i32) -> Result<(), LuaError> {
360        todo!("phase-b-reconcile: len_op")
361    }
362    fn arith(&mut self, op: ArithOp) -> Result<(), LuaError> {
363        todo!("phase-b-reconcile: arith")
364    }
365
366    fn load(&mut self, chunk: &[u8], name: &[u8], mode: Option<&[u8]>) -> Result<bool, LuaError> {
367        todo!("phase-b-reconcile: load")
368    }
369    fn load_buffer_ex<M: ?Sized>(
370        &mut self,
371        buf: &[u8],
372        name: &[u8],
373        mode: &M,
374    ) -> Result<bool, LuaError>
375    where
376        M: AsRef<[u8]>,
377    {
378        let _ = (buf, name, mode);
379        todo!("phase-b-reconcile: load_buffer_ex")
380    }
381    fn load_file(&mut self, path: Option<&[u8]>) -> Result<bool, LuaError> {
382        todo!("phase-b-reconcile: load_file")
383    }
384    fn load_file_ex(&mut self, path: Option<&[u8]>, mode: Option<&[u8]>) -> Result<bool, LuaError> {
385        todo!("phase-b-reconcile: load_file_ex")
386    }
387    fn load_with_reader<F, M: ?Sized>(
388        &mut self,
389        reader: F,
390        name: &[u8],
391        mode: &M,
392    ) -> Result<bool, LuaError>
393    where
394        F: FnMut(&mut LuaState) -> Result<Option<Vec<u8>>, LuaError>,
395        M: AsRef<[u8]>,
396    {
397        let _ = (reader, name, mode);
398        todo!("phase-b-reconcile: load_with_reader")
399    }
400    fn dump_function(&mut self, strip: bool) -> Result<Vec<u8>, LuaError> {
401        todo!("phase-b-reconcile: dump_function")
402    }
403
404    fn warning(&mut self, msg: &[u8], to_cont: bool) -> Result<(), LuaError> {
405        todo!("phase-b-reconcile: warning")
406    }
407    fn write_output(&mut self, msg: &[u8]) -> Result<(), LuaError> {
408        todo!("phase-b-reconcile: write_output")
409    }
410    fn set_warn_fn(
411        &mut self,
412        f: Option<lua_CFunction>,
413        ud: Option<LuaValue>,
414    ) -> Result<(), LuaError> {
415        todo!("phase-b-reconcile: set_warn_fn")
416    }
417    fn set_funcs(&mut self, funcs: &[(&[u8], lua_CFunction)], nup: i32) -> Result<(), LuaError> {
418        let _ = (funcs, nup);
419        todo!("phase-b-reconcile: set_funcs")
420    }
421    fn set_global(&mut self, name: &[u8]) -> Result<(), LuaError> {
422        todo!("phase-b-reconcile: set_global")
423    }
424    fn set_upvalue(&mut self, fidx: i32, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
425        todo!("phase-b-reconcile: set_upvalue")
426    }
427    fn get_info(&mut self, what: &[u8], ar: &mut LuaDebug) -> Result<(), LuaError> {
428        todo!("phase-b-reconcile: get_info")
429    }
430    fn get_stack(&mut self, level: i32, ar: &mut LuaDebug) -> bool {
431        todo!("phase-b-reconcile: get_stack")
432    }
433    fn lua_version(&mut self) -> f64 {
434        todo!("phase-b-reconcile: lua_version")
435    }
436    fn string_to_number(&mut self, idx: i32) -> Option<usize> {
437        todo!("phase-b-reconcile: string_to_number")
438    }
439    fn string_to_number_push<S: AsRef<[u8]> + ?Sized>(&mut self, s: &S) -> Result<usize, LuaError> {
440        let _ = s.as_ref();
441        todo!("phase-b-reconcile: string_to_number_push")
442    }
443    fn require_lib(
444        &mut self,
445        name: &[u8],
446        openf: lua_CFunction,
447        glb: bool,
448    ) -> Result<(), LuaError> {
449        todo!("phase-b-reconcile: require_lib")
450    }
451    fn peek_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
452        todo!("phase-b-reconcile: peek_bytes")
453    }
454
455    fn check_number(&mut self, arg: i32) -> Result<f64, LuaError> {
456        todo!("phase-b-reconcile: check_number")
457    }
458    fn check_integer(&mut self, arg: i32) -> Result<i64, LuaError> {
459        todo!("phase-b-reconcile: check_integer")
460    }
461    fn check_any(&mut self, arg: i32) -> Result<(), LuaError> {
462        todo!("phase-b-reconcile: check_any")
463    }
464    fn check_arg_number(&mut self, arg: i32) -> Result<f64, LuaError> {
465        todo!("phase-b-reconcile: check_arg_number")
466    }
467    fn check_arg_userdata(
468        &mut self,
469        arg: i32,
470        name: &[u8],
471    ) -> Result<GcRef<LuaUserData>, LuaError> {
472        todo!("phase-b-reconcile: check_arg_userdata")
473    }
474    fn check_stack_growth(&mut self, n: i32) -> bool {
475        todo!("phase-b-reconcile: check_stack_growth")
476    }
477    fn opt_integer(&mut self, arg: i32, def: i64) -> Result<i64, LuaError> {
478        todo!("phase-b-reconcile: opt_integer")
479    }
480    fn opt_number(&mut self, arg: i32, def: f64) -> Result<f64, LuaError> {
481        todo!("phase-b-reconcile: opt_number")
482    }
483    fn opt_arg_lstring(
484        &mut self,
485        arg: i32,
486        def: Option<&[u8]>,
487    ) -> Result<Option<Vec<u8>>, LuaError> {
488        todo!("phase-b-reconcile: opt_arg_lstring")
489    }
490
491    fn table_get_i(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
492        todo!("phase-b-reconcile: table_get_i")
493    }
494    fn table_set_i(&mut self, idx: i32, n: i64) -> Result<(), LuaError> {
495        todo!("phase-b-reconcile: table_set_i")
496    }
497    fn table_get_i_value(&mut self, t: &LuaValue, n: i64) -> Result<LuaType, LuaError> {
498        todo!("phase-b-reconcile: table_get_i_value")
499    }
500    fn table_set_i_value(&mut self, t: &LuaValue, n: i64) -> Result<(), LuaError> {
501        todo!("phase-b-reconcile: table_set_i_value")
502    }
503    fn get_table(&mut self, idx: i32) -> Result<LuaType, LuaError> {
504        todo!("phase-b-reconcile: get_table")
505    }
506    fn raw_geti(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
507        todo!("phase-b-reconcile: raw_geti")
508    }
509    fn raw_seti(&mut self, idx: i32, n: i64) -> Result<(), LuaError> {
510        todo!("phase-b-reconcile: raw_seti")
511    }
512    fn len_at(&mut self, idx: i32) -> i64 {
513        todo!("phase-b-reconcile: len_at")
514    }
515    fn length_at(&mut self, idx: i32) -> Result<i64, LuaError> {
516        todo!("phase-b-reconcile: length_at")
517    }
518    fn stack_top(&mut self) -> i32 {
519        todo!("phase-b-reconcile: stack_top")
520    }
521    fn get_top(&mut self) -> i32 {
522        todo!("phase-b-reconcile: get_top")
523    }
524
525    fn push_value_at(&mut self, idx: i32) -> Result<(), LuaError> {
526        todo!("phase-b-reconcile: push_value_at")
527    }
528    fn push_fail(&mut self) -> Result<(), LuaError> {
529        todo!("phase-b-reconcile: push_fail")
530    }
531    fn push_lstring(&mut self, s: &[u8]) -> Result<(), LuaError> {
532        todo!("phase-b-reconcile: push_lstring")
533    }
534    fn push_thread(&mut self) -> Result<bool, LuaError> {
535        todo!("phase-b-reconcile: push_thread")
536    }
537    fn push_cclosure(&mut self, f: lua_CFunction, n: i32) -> Result<(), LuaError> {
538        todo!("phase-b-reconcile: push_cclosure")
539    }
540    fn push_upvalue(&mut self, idx: i32) -> Result<(), LuaError> {
541        todo!("phase-b-reconcile: push_upvalue")
542    }
543    fn push_registry(&mut self) -> Result<(), LuaError> {
544        todo!("phase-b-reconcile: push_registry")
545    }
546
547    fn to_integer(&mut self, idx: i32) -> Option<i64> {
548        todo!("phase-b-reconcile: to_integer")
549    }
550    fn to_integer_opt(&mut self, idx: i32) -> Option<i64> {
551        todo!("phase-b-reconcile: to_integer_opt")
552    }
553    fn to_number(&mut self, idx: i32) -> Option<f64> {
554        todo!("phase-b-reconcile: to_number")
555    }
556    fn to_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
557        todo!("phase-b-reconcile: to_bytes")
558    }
559    fn to_bytes_at(&mut self, idx: i32) -> Option<Vec<u8>> {
560        todo!("phase-b-reconcile: to_bytes_at")
561    }
562    fn to_string_coerced(&mut self, idx: i32) -> Option<Vec<u8>> {
563        todo!("phase-b-reconcile: to_string_coerced")
564    }
565    fn to_light_userdata(&mut self, idx: i32) -> Option<*mut std::ffi::c_void> {
566        todo!("phase-b-reconcile: to_light_userdata")
567    }
568    fn to_thread(&mut self, idx: i32) -> Option<GcRef<LuaThread>> {
569        todo!("phase-b-reconcile: to_thread")
570    }
571    fn to_thread_at(&mut self, idx: i32) -> Option<GcRef<LuaThread>> {
572        todo!("phase-b-reconcile: to_thread_at")
573    }
574    fn type_name_str_at(&mut self, idx: i32) -> &'static [u8] {
575        todo!("phase-b-reconcile: type_name_str_at")
576    }
577    fn is_c_function_at(&mut self, idx: i32) -> bool {
578        todo!("phase-b-reconcile: is_c_function_at")
579    }
580
581    fn compare(&mut self, idx1: i32, idx2: i32, op: CompareOp) -> Result<bool, LuaError> {
582        todo!("phase-b-reconcile: compare")
583    }
584    fn compare_lt(&mut self, idx1: i32, idx2: i32) -> Result<bool, LuaError> {
585        todo!("phase-b-reconcile: compare_lt")
586    }
587
588    fn get_field_registry(&mut self, name: &[u8]) -> Result<LuaType, LuaError> {
589        todo!("phase-b-reconcile: get_field_registry")
590    }
591    fn get_registry_field(&mut self, name: &[u8]) -> Result<LuaType, LuaError> {
592        todo!("phase-b-reconcile: get_registry_field")
593    }
594    fn get_subtable_registry(&mut self, name: &[u8]) -> Result<bool, LuaError> {
595        todo!("phase-b-reconcile: get_subtable_registry")
596    }
597    fn get_or_create_registry_subtable(&mut self, name: &[u8]) -> Result<bool, LuaError> {
598        todo!("phase-b-reconcile: get_or_create_registry_subtable")
599    }
600    fn registry_get(&mut self, key: &[u8]) -> Result<LuaType, LuaError> {
601        todo!("phase-b-reconcile: registry_get")
602    }
603    fn registry_set(&mut self, key: &[u8]) -> Result<(), LuaError> {
604        todo!("phase-b-reconcile: registry_set")
605    }
606
607    fn new_lib<F: Copy>(&mut self, funcs: &[(&[u8], F)]) -> Result<(), LuaError> {
608        todo!("phase-b-reconcile: new_lib")
609    }
610    fn new_lib_table<F: Copy>(&mut self, funcs: &[(&[u8], F)]) -> Result<(), LuaError> {
611        todo!("phase-b-reconcile: new_lib_table")
612    }
613    fn new_metatable(&mut self, name: &[u8]) -> Result<bool, LuaError> {
614        todo!("phase-b-reconcile: new_metatable")
615    }
616    fn set_metatable_by_name(&mut self, name: &[u8]) -> Result<(), LuaError> {
617        todo!("phase-b-reconcile: set_metatable_by_name")
618    }
619    fn register_funcs<F: Copy>(&mut self, funcs: &[(&[u8], F)]) -> Result<(), LuaError> {
620        todo!("phase-b-reconcile: register_funcs")
621    }
622    fn register_lib<F: Copy>(&mut self, name: &[u8], funcs: &[(&[u8], F)]) -> Result<(), LuaError> {
623        todo!("phase-b-reconcile: register_lib")
624    }
625    fn set_funcs_with_upvalues<F: Copy>(
626        &mut self,
627        funcs: &[(&[u8], F)],
628        nup: i32,
629    ) -> Result<(), LuaError> {
630        todo!("phase-b-reconcile: set_funcs_with_upvalues")
631    }
632
633    fn new_userdata_typed(
634        &mut self,
635        name: &[u8],
636        size: usize,
637        nuvalue: i32,
638    ) -> Result<GcRef<LuaUserData>, LuaError> {
639        todo!("phase-b-reconcile: new_userdata_typed")
640    }
641    fn get_iuservalue(&mut self, idx: i32, n: i32) -> Result<LuaType, LuaError> {
642        todo!("phase-b-reconcile: get_iuservalue")
643    }
644    fn set_iuservalue(&mut self, idx: i32, n: i32) -> Result<bool, LuaError> {
645        todo!("phase-b-reconcile: set_iuservalue")
646    }
647    fn test_arg_userdata(&mut self, arg: i32, name: &[u8]) -> Option<GcRef<LuaUserData>> {
648        todo!("phase-b-reconcile: test_arg_userdata")
649    }
650
651    fn get_upvalue(&mut self, fidx: i32, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
652        todo!("phase-b-reconcile: get_upvalue")
653    }
654    fn upvalue_id(&mut self, fidx: i32, n: i32) -> Result<*mut std::ffi::c_void, LuaError> {
655        todo!("phase-b-reconcile: upvalue_id")
656    }
657    fn join_upvalues(&mut self, fidx1: i32, n1: i32, fidx2: i32, n2: i32) -> Result<(), LuaError> {
658        todo!("phase-b-reconcile: join_upvalues")
659    }
660    fn upvalue_index(&mut self, i: i32) -> i32 {
661        upvalue_index(i)
662    }
663    fn close(&mut self) {
664        todo!("phase-b-reconcile: close")
665    }
666    fn set_hook_full(
667        &mut self,
668        f: Option<lua_CFunction>,
669        mask: u32,
670        count: i32,
671    ) -> Result<(), LuaError> {
672        todo!("phase-b-reconcile: set_hook_full")
673    }
674
675    fn get_local_at(&mut self, ar: &LuaDebug, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
676        todo!("phase-b-reconcile: get_local_at")
677    }
678    fn set_local_at(&mut self, ar: &LuaDebug, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
679        todo!("phase-b-reconcile: set_local_at")
680    }
681    fn get_param_name(&mut self, fidx: i32, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
682        todo!("phase-b-reconcile: get_param_name")
683    }
684
685    fn get_debug_info(&mut self, what: &[u8], ar: &mut LuaDebug) -> Result<(), LuaError> {
686        todo!("phase-b-reconcile: get_debug_info")
687    }
688    fn get_stack_level(&mut self, level: i32, ar: &mut LuaDebug) -> bool {
689        todo!("phase-b-reconcile: get_stack_level")
690    }
691    fn has_frames(&mut self) -> bool {
692        todo!("phase-b-reconcile: has_frames")
693    }
694    fn lua_traceback(
695        &mut self,
696        other: &mut LuaState,
697        msg: Option<&[u8]>,
698        level: i32,
699    ) -> Result<(), LuaError> {
700        todo!("phase-b-reconcile: lua_traceback")
701    }
702
703    fn get_hook_count(&mut self) -> i32 {
704        todo!("phase-b-reconcile: get_hook_count")
705    }
706    fn get_hook_mask(&mut self) -> u32 {
707        todo!("phase-b-reconcile: get_hook_mask")
708    }
709    fn hook_is_set(&mut self) -> bool {
710        todo!("phase-b-reconcile: hook_is_set")
711    }
712    fn hook_is_internal_lua_hook(&mut self) -> bool {
713        todo!("phase-b-reconcile: hook_is_internal_lua_hook")
714    }
715    fn set_c_stack_limit(&mut self, limit: i32) -> Result<i32, LuaError> {
716        todo!("phase-b-reconcile: set_c_stack_limit")
717    }
718
719    fn new_thread(&mut self, initial_body: Option<LuaValue>) -> Result<GcRef<LuaThread>, LuaError> {
720        let _ = initial_body;
721        todo!("phase-b-reconcile: new_thread")
722    }
723    fn is_same_thread(&mut self, other: &LuaState) -> bool {
724        todo!("phase-b-reconcile: is_same_thread")
725    }
726    fn thread_status(&mut self) -> LuaStatus {
727        todo!("phase-b-reconcile: thread_status")
728    }
729
730    fn load_buffer(
731        &mut self,
732        buf: &[u8],
733        name: &[u8],
734        mode: Option<&[u8]>,
735    ) -> Result<LuaStatus, LuaError> {
736        todo!("phase-b-reconcile: load_buffer")
737    }
738    fn where_error(&mut self, level: i32, msg: &[u8]) -> LuaError {
739        todo!("phase-b-reconcile: where_error")
740    }
741    fn arg(&mut self, n: i32) -> LuaValue {
742        todo!("phase-b-reconcile: arg")
743    }
744    fn as_bytes_or_coerce(&mut self, idx: i32) -> Option<Vec<u8>> {
745        todo!("phase-b-reconcile: as_bytes_or_coerce")
746    }
747    fn as_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
748        todo!("phase-b-reconcile: as_bytes")
749    }
750}
751
752impl LuaStateStubExt for LuaState {
753    fn require_lib(
754        &mut self,
755        name: &[u8],
756        openf: lua_CFunction,
757        glb: bool,
758    ) -> Result<(), LuaError> {
759        crate::auxlib::requiref(self, name, openf, glb)
760    }
761
762    fn get_field(&mut self, idx: i32, k: &[u8]) -> Result<LuaType, LuaError> {
763        lua_vm::api::get_field(self, idx, k)
764    }
765
766    fn abs_index(&mut self, idx: i32) -> i32 {
767        lua_vm::api::abs_index(self, idx)
768    }
769
770    fn push_value(&mut self, idx: i32) -> Result<(), LuaError> {
771        lua_vm::api::push_value(self, idx);
772        Ok(())
773    }
774
775    fn set_field(&mut self, idx: i32, k: &[u8]) -> Result<(), LuaError> {
776        lua_vm::api::set_field(self, idx, k)
777    }
778
779    fn set_global(&mut self, name: &[u8]) -> Result<(), LuaError> {
780        lua_vm::api::set_global(self, name)
781    }
782
783    fn to_boolean(&mut self, idx: i32) -> bool {
784        lua_vm::api::to_boolean(self, idx)
785    }
786
787    fn top(&mut self) -> i32 {
788        lua_vm::api::get_top(self)
789    }
790
791    fn push_c_function(&mut self, f: lua_CFunction) -> Result<(), LuaError> {
792        let idx: LuaCFnPtr = {
793            let mut g = self.global_mut();
794            match g.c_functions.iter().position(|existing| {
795                existing
796                    .as_bare()
797                    .is_some_and(|existing| std::ptr::fn_addr_eq(existing, f))
798            }) {
799                Some(i) => i,
800                None => {
801                    let i = g.c_functions.len();
802                    g.c_functions.push(LuaCallable::bare(f));
803                    i
804                }
805            }
806        };
807        self.push(LuaValue::Function(LuaClosure::LightC(idx)));
808        Ok(())
809    }
810
811    fn push_bytes(&mut self, s: &[u8]) -> Result<(), LuaError> {
812        lua_vm::api::push_lstring(self, s)?;
813        Ok(())
814    }
815
816    fn call(&mut self, nargs: i32, nresults: i32) -> Result<(), LuaError> {
817        lua_vm::api::call_k(self, nargs, nresults, 0, None)
818    }
819
820    fn call_k(
821        &mut self,
822        nargs: i32,
823        nresults: i32,
824        ctx: isize,
825        k: Option<fn(&mut LuaState, i32, isize) -> Result<usize, LuaError>>,
826    ) -> Result<(), LuaError> {
827        lua_vm::api::call_k(self, nargs, nresults, ctx, k)
828    }
829
830    fn remove(&mut self, idx: i32) -> Result<(), LuaError> {
831        lua_vm::api::rotate(self, idx, -1);
832        lua_vm::api::set_top(self, -2)
833    }
834
835    fn get_upvalue(&mut self, fidx: i32, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
836        Ok(lua_vm::api::get_upvalue(self, fidx, n))
837    }
838
839    fn set_upvalue(&mut self, fidx: i32, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
840        Ok(lua_vm::api::setup_value(self, fidx, n))
841    }
842
843    fn load(&mut self, chunk: &[u8], name: &[u8], mode: Option<&[u8]>) -> Result<bool, LuaError> {
844        let mut remaining = Some(chunk.to_vec());
845        let reader: Box<dyn FnMut() -> Option<Vec<u8>>> = Box::new(move || remaining.take());
846        let status = lua_vm::api::load(self, reader, Some(name), mode)?;
847        Ok(status == LuaStatus::Ok)
848    }
849
850    fn push_globals(&mut self) -> Result<(), LuaError> {
851        let g = self.global().globals.clone();
852        self.push(g);
853        Ok(())
854    }
855
856    fn set_funcs(&mut self, funcs: &[(&[u8], lua_CFunction)], nup: i32) -> Result<(), LuaError> {
857        lua_vm::api::check_stack(self, nup);
858        for (name, f) in funcs {
859            for _ in 0..nup {
860                lua_vm::api::push_value(self, -nup);
861            }
862            lua_vm::api::push_cclosure(self, *f, nup)?;
863            lua_vm::api::set_field(self, -(nup + 2), name)?;
864        }
865        self.pop_n(nup as usize);
866        Ok(())
867    }
868
869    fn arg_to_bool(&mut self, arg: i32) -> bool {
870        lua_vm::api::to_boolean(self, arg)
871    }
872
873    fn value_at(&mut self, idx: i32) -> LuaValue {
874        lua_vm::api::push_value(self, idx);
875        self.pop()
876    }
877
878    fn check_arg_type(&mut self, arg: i32, t: LuaType) -> Result<(), LuaError> {
879        if lua_vm::api::lua_type_at(self, arg) != t {
880            lua_vm::api::push_value(self, arg);
881            let got = self.pop();
882            let expected: &str = match t {
883                LuaType::None => "no value",
884                LuaType::Nil => "nil",
885                LuaType::Boolean => "boolean",
886                LuaType::LightUserData => "userdata",
887                LuaType::Number => "number",
888                LuaType::String => "string",
889                LuaType::Table => "table",
890                LuaType::Function => "function",
891                LuaType::UserData => "userdata",
892                LuaType::Thread => "thread",
893            };
894            let got_name = if lua_vm::api::lua_type_at(self, arg) == LuaType::None {
895                b"no value".to_vec()
896            } else {
897                self.full_type_name(&got)?
898            };
899            let extramsg = format!(
900                "{} expected, got {}",
901                expected,
902                String::from_utf8_lossy(&got_name)
903            );
904            return Err(lua_vm::debug::arg_error_impl(
905                self,
906                arg,
907                extramsg.as_bytes(),
908            ));
909        }
910        Ok(())
911    }
912
913    fn opt_arg_string(&mut self, arg: i32, def: &[u8]) -> Result<Vec<u8>, LuaError> {
914        match lua_vm::api::lua_type_at(self, arg) {
915            LuaType::None | LuaType::Nil => Ok(def.to_vec()),
916            _ => self.check_arg_string(arg),
917        }
918    }
919
920    fn get_metafield(&mut self, idx: i32, name: &[u8]) -> Result<LuaType, LuaError> {
921        let abs = lua_vm::api::abs_index(self, idx);
922        if !lua_vm::api::get_metatable(self, abs) {
923            return Ok(LuaType::Nil);
924        }
925        lua_vm::api::push_lstring(self, name)?;
926        let tt = lua_vm::api::raw_get(self, -2);
927        if tt == LuaType::Nil {
928            self.pop_n(2);
929        } else {
930            self.remove(-2)?;
931        }
932        Ok(tt)
933    }
934
935    fn table_get_i(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
936        lua_vm::api::get_i(self, idx, n)
937    }
938
939    fn table_get_i_value(&mut self, t: &LuaValue, n: i64) -> Result<LuaType, LuaError> {
940        lua_vm::api::get_i_value(self, t, n)
941    }
942
943    fn table_set_i_value(&mut self, t: &LuaValue, n: i64) -> Result<(), LuaError> {
944        lua_vm::api::set_i_value(self, t, n)
945    }
946
947    fn compare_lt(&mut self, idx1: i32, idx2: i32) -> Result<bool, LuaError> {
948        lua_vm::api::compare(self, idx1, idx2, 1)
949    }
950
951    fn check_arg_any(&mut self, arg: i32) -> Result<(), LuaError> {
952        if lua_vm::api::lua_type_at(self, arg) == LuaType::None {
953            return Err(LuaError::arg_error(arg, "value expected"));
954        }
955        Ok(())
956    }
957
958    fn check_arg_integer(&mut self, arg: i32) -> Result<i64, LuaError> {
959        match lua_vm::api::to_integer_x(self, arg) {
960            Some(d) => Ok(d),
961            None => {
962                if lua_vm::api::is_number(self, arg) {
963                    Err(LuaError::arg_error(
964                        arg,
965                        "number has no integer representation",
966                    ))
967                } else {
968                    let got = self.value_at(arg);
969                    let got_name = if lua_vm::api::lua_type_at(self, arg) == LuaType::None {
970                        b"no value".to_vec()
971                    } else {
972                        self.full_type_name(&got)?
973                    };
974                    let extramsg = format!(
975                        "number expected, got {}",
976                        String::from_utf8_lossy(&got_name)
977                    );
978                    Err(lua_vm::debug::arg_error_impl(
979                        self,
980                        arg,
981                        extramsg.as_bytes(),
982                    ))
983                }
984            }
985        }
986    }
987
988    fn check_arg_string(&mut self, arg: i32) -> Result<Vec<u8>, LuaError> {
989        match lua_vm::api::to_lua_string(self, arg)? {
990            Some(s) => Ok(s.as_bytes().to_vec()),
991            None => {
992                let got = self.value_at(arg);
993                let got_name = if lua_vm::api::lua_type_at(self, arg) == LuaType::None {
994                    b"no value".to_vec()
995                } else {
996                    self.full_type_name(&got)?
997                };
998                let extramsg = format!(
999                    "string expected, got {}",
1000                    String::from_utf8_lossy(&got_name)
1001                );
1002                Err(lua_vm::debug::arg_error_impl(
1003                    self,
1004                    arg,
1005                    extramsg.as_bytes(),
1006                ))
1007            }
1008        }
1009    }
1010
1011    fn check_arg_number(&mut self, arg: i32) -> Result<f64, LuaError> {
1012        match lua_vm::api::to_number_x(self, arg) {
1013            Some(d) => Ok(d),
1014            None => {
1015                let got = self.value_at(arg);
1016                let got_name = if lua_vm::api::lua_type_at(self, arg) == LuaType::None {
1017                    b"no value".to_vec()
1018                } else {
1019                    self.full_type_name(&got)?
1020                };
1021                let extramsg = format!(
1022                    "number expected, got {}",
1023                    String::from_utf8_lossy(&got_name)
1024                );
1025                Err(lua_vm::debug::arg_error_impl(
1026                    self,
1027                    arg,
1028                    extramsg.as_bytes(),
1029                ))
1030            }
1031        }
1032    }
1033
1034    fn check_number(&mut self, arg: i32) -> Result<f64, LuaError> {
1035        self.check_arg_number(arg)
1036    }
1037
1038    fn check_integer(&mut self, arg: i32) -> Result<i64, LuaError> {
1039        self.check_arg_integer(arg)
1040    }
1041
1042    fn check_any(&mut self, arg: i32) -> Result<(), LuaError> {
1043        self.check_arg_any(arg)
1044    }
1045
1046    fn opt_arg_integer(&mut self, arg: i32, def: i64) -> Result<i64, LuaError> {
1047        match lua_vm::api::lua_type_at(self, arg) {
1048            LuaType::None | LuaType::Nil => Ok(def),
1049            _ => self.check_arg_integer(arg),
1050        }
1051    }
1052
1053    fn opt_integer(&mut self, arg: i32, def: i64) -> Result<i64, LuaError> {
1054        self.opt_arg_integer(arg, def)
1055    }
1056
1057    fn opt_number(&mut self, arg: i32, def: f64) -> Result<f64, LuaError> {
1058        match lua_vm::api::lua_type_at(self, arg) {
1059            LuaType::None | LuaType::Nil => Ok(def),
1060            _ => self.check_arg_number(arg),
1061        }
1062    }
1063
1064    fn opt_arg_string_bytes(&mut self, arg: i32) -> Result<Vec<u8>, LuaError> {
1065        match lua_vm::api::lua_type_at(self, arg) {
1066            LuaType::None | LuaType::Nil => Ok(Vec::new()),
1067            _ => self.check_arg_string(arg),
1068        }
1069    }
1070
1071    fn opt_arg_lstring(
1072        &mut self,
1073        arg: i32,
1074        def: Option<&[u8]>,
1075    ) -> Result<Option<Vec<u8>>, LuaError> {
1076        match lua_vm::api::lua_type_at(self, arg) {
1077            LuaType::None | LuaType::Nil => Ok(def.map(|d| d.to_vec())),
1078            _ => Ok(Some(self.check_arg_string(arg)?)),
1079        }
1080    }
1081
1082    fn check_arg_option(
1083        &mut self,
1084        arg: i32,
1085        def: Option<&[u8]>,
1086        lst: &[&[u8]],
1087    ) -> Result<usize, LuaError> {
1088        let name: Vec<u8> = match def {
1089            Some(d)
1090                if matches!(
1091                    lua_vm::api::lua_type_at(self, arg),
1092                    LuaType::None | LuaType::Nil
1093                ) =>
1094            {
1095                d.to_vec()
1096            }
1097            _ => self.check_arg_string(arg)?,
1098        };
1099        for (i, entry) in lst.iter().enumerate() {
1100            if *entry == name.as_slice() {
1101                return Ok(i);
1102            }
1103        }
1104        let extramsg = format!("invalid option '{}'", String::from_utf8_lossy(&name));
1105        Err(lua_vm::debug::arg_error_impl(
1106            self,
1107            arg,
1108            extramsg.as_bytes(),
1109        ))
1110    }
1111
1112    fn arg(&mut self, n: i32) -> LuaValue {
1113        self.value_at(n)
1114    }
1115
1116    fn type_at(&mut self, idx: i32) -> LuaType {
1117        lua_vm::api::lua_type_at(self, idx)
1118    }
1119
1120    fn type_name(&mut self, t: LuaType) -> &'static [u8] {
1121        lua_vm::api::type_name(self, t)
1122    }
1123
1124    fn type_name_at(&mut self, idx: i32) -> &'static [u8] {
1125        let t = lua_vm::api::lua_type_at(self, idx);
1126        lua_vm::api::type_name(self, t)
1127    }
1128
1129    fn is_integer(&mut self, idx: i32) -> bool {
1130        lua_vm::api::is_integer(self, idx)
1131    }
1132
1133    fn is_number(&mut self, idx: i32) -> bool {
1134        lua_vm::api::is_number(self, idx)
1135    }
1136
1137    fn is_none_or_nil(&mut self, idx: i32) -> bool {
1138        matches!(
1139            lua_vm::api::lua_type_at(self, idx),
1140            LuaType::None | LuaType::Nil
1141        )
1142    }
1143
1144    fn to_integer_x(&mut self, idx: i32) -> Option<i64> {
1145        lua_vm::api::to_integer_x(self, idx)
1146    }
1147
1148    fn to_number_x(&mut self, idx: i32) -> Option<f64> {
1149        lua_vm::api::to_number_x(self, idx)
1150    }
1151
1152    fn to_integer(&mut self, idx: i32) -> Option<i64> {
1153        lua_vm::api::to_integer_x(self, idx)
1154    }
1155
1156    fn to_integer_opt(&mut self, idx: i32) -> Option<i64> {
1157        lua_vm::api::to_integer_x(self, idx)
1158    }
1159
1160    fn to_number(&mut self, idx: i32) -> Option<f64> {
1161        lua_vm::api::to_number_x(self, idx)
1162    }
1163
1164    fn to_lua_string(&mut self, idx: i32) -> Option<GcRef<LuaString>> {
1165        lua_vm::api::to_lua_string(self, idx).ok().flatten()
1166    }
1167
1168    fn to_lua_string_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
1169        lua_vm::api::to_lua_string(self, idx)
1170            .ok()
1171            .flatten()
1172            .map(|s| s.as_bytes().to_vec())
1173    }
1174
1175    fn to_lua_string_len(&mut self, idx: i32) -> Option<usize> {
1176        lua_vm::api::to_lua_string(self, idx)
1177            .ok()
1178            .flatten()
1179            .map(|s| s.len())
1180    }
1181
1182    fn to_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
1183        self.to_lua_string_bytes(idx)
1184    }
1185
1186    fn to_bytes_at(&mut self, idx: i32) -> Option<Vec<u8>> {
1187        self.to_lua_string_bytes(idx)
1188    }
1189
1190    fn raw_equal(&mut self, idx1: i32, idx2: i32) -> Result<bool, LuaError> {
1191        Ok(lua_vm::api::raw_equal(self, idx1, idx2))
1192    }
1193
1194    fn raw_geti(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
1195        Ok(lua_vm::api::raw_get_i(self, idx, n))
1196    }
1197
1198    fn raw_get_i(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
1199        Ok(lua_vm::api::raw_get_i(self, idx, n))
1200    }
1201
1202    fn raw_seti(&mut self, idx: i32, n: i64) -> Result<(), LuaError> {
1203        lua_vm::api::raw_set_i(self, idx, n)
1204    }
1205
1206    fn raw_set_i(&mut self, idx: i32, n: i64) -> Result<(), LuaError> {
1207        lua_vm::api::raw_set_i(self, idx, n)
1208    }
1209
1210    fn raw_len(&mut self, idx: i32) -> i64 {
1211        lua_vm::api::raw_len(self, idx) as i64
1212    }
1213
1214    fn get_i(&mut self, idx: i32, n: i64) -> Result<LuaType, LuaError> {
1215        lua_vm::api::get_i(self, idx, n)
1216    }
1217
1218    fn get_metatable(&mut self, idx: i32) -> Result<bool, LuaError> {
1219        Ok(lua_vm::api::get_metatable(self, idx))
1220    }
1221
1222    fn set_metatable(&mut self, idx: i32) -> Result<(), LuaError> {
1223        lua_vm::api::set_metatable(self, idx)?;
1224        Ok(())
1225    }
1226
1227    fn compare(&mut self, idx1: i32, idx2: i32, op: CompareOp) -> Result<bool, LuaError> {
1228        let op_i = match op {
1229            CompareOp::Eq => 0,
1230            CompareOp::Lt => 1,
1231            CompareOp::Le => 2,
1232        };
1233        lua_vm::api::compare(self, idx1, idx2, op_i)
1234    }
1235
1236    fn protected_call(&mut self, nargs: i32, nresults: i32, msgh: i32) -> Result<(), LuaError> {
1237        lua_vm::api::pcall_k(self, nargs, nresults, msgh, 0, None)?;
1238        Ok(())
1239    }
1240    fn protected_call_k(
1241        &mut self,
1242        nargs: i32,
1243        nresults: i32,
1244        msgh: i32,
1245        ctx: isize,
1246        k: Option<fn(&mut LuaState, i32, isize) -> Result<usize, LuaError>>,
1247    ) -> Result<(), LuaError> {
1248        lua_vm::api::pcall_k(self, nargs, nresults, msgh, ctx, k)?;
1249        Ok(())
1250    }
1251
1252    fn push_value_at(&mut self, idx: i32) -> Result<(), LuaError> {
1253        lua_vm::api::push_value(self, idx);
1254        Ok(())
1255    }
1256
1257    fn push_thread(&mut self) -> Result<bool, LuaError> {
1258        Ok(lua_vm::api::push_thread(self))
1259    }
1260
1261    fn push_cclosure(&mut self, f: lua_CFunction, n: i32) -> Result<(), LuaError> {
1262        lua_vm::api::push_cclosure(self, f, n)
1263    }
1264
1265    fn push_c_closure(&mut self, f: lua_CFunction, n: i32) -> Result<(), LuaError> {
1266        lua_vm::api::push_cclosure(self, f, n)
1267    }
1268
1269    fn push_lstring(&mut self, s: &[u8]) -> Result<(), LuaError> {
1270        lua_vm::api::push_lstring(self, s)?;
1271        Ok(())
1272    }
1273
1274    fn push_string(&mut self, s: &[u8]) -> Result<(), LuaError> {
1275        lua_vm::api::push_lstring(self, s)?;
1276        Ok(())
1277    }
1278
1279    fn get_top(&mut self) -> i32 {
1280        lua_vm::api::get_top(self)
1281    }
1282
1283    fn stack_top(&mut self) -> i32 {
1284        lua_vm::api::get_top(self)
1285    }
1286
1287    fn top_count(&mut self) -> i32 {
1288        lua_vm::api::get_top(self)
1289    }
1290
1291    fn check_stack_space(&mut self, n: i32) -> bool {
1292        lua_vm::api::check_stack(self, n)
1293    }
1294
1295    fn rotate(&mut self, idx: i32, n: i32) -> Result<(), LuaError> {
1296        lua_vm::api::rotate(self, idx, n);
1297        Ok(())
1298    }
1299
1300    fn insert(&mut self, idx: i32) -> Result<(), LuaError> {
1301        lua_vm::api::rotate(self, idx, 1);
1302        Ok(())
1303    }
1304
1305    fn copy_value(&mut self, from: i32, to: i32) -> Result<(), LuaError> {
1306        lua_vm::api::copy(self, from, to);
1307        Ok(())
1308    }
1309
1310    fn replace(&mut self, idx: i32) -> Result<(), LuaError> {
1311        lua_vm::api::copy(self, -1, idx);
1312        lua_vm::api::set_top(self, -2)
1313    }
1314
1315    fn len_op(&mut self, idx: i32) -> Result<(), LuaError> {
1316        lua_vm::api::len(self, idx)
1317    }
1318
1319    fn table_next(&mut self, idx: i32) -> Result<bool, LuaError> {
1320        lua_vm::api::next(self, idx)
1321    }
1322
1323    fn create_table(&mut self, narr: i32, nrec: i32) -> Result<(), LuaError> {
1324        lua_vm::api::create_table(self, narr, nrec)
1325    }
1326
1327    fn to_userdata(&mut self, idx: i32) -> Option<GcRef<LuaUserData>> {
1328        let v = self.value_at(idx);
1329        if let LuaValue::UserData(u) = v {
1330            Some(u)
1331        } else {
1332            None
1333        }
1334    }
1335
1336    fn to_light_userdata(&mut self, idx: i32) -> Option<*mut std::ffi::c_void> {
1337        lua_vm::api::to_userdata(self, idx)
1338    }
1339
1340    fn to_thread(&mut self, idx: i32) -> Option<GcRef<LuaThread>> {
1341        lua_vm::api::to_thread(self, idx)
1342    }
1343
1344    fn to_thread_at(&mut self, idx: i32) -> Option<GcRef<LuaThread>> {
1345        lua_vm::api::to_thread(self, idx)
1346    }
1347
1348    fn len_at(&mut self, idx: i32) -> i64 {
1349        lua_vm::api::raw_len(self, idx) as i64
1350    }
1351
1352    fn length_at(&mut self, idx: i32) -> Result<i64, LuaError> {
1353        lua_vm::api::len(self, idx)?;
1354        let v = lua_vm::api::to_integer_x(self, -1);
1355        self.pop_n(1);
1356        match v {
1357            Some(l) => Ok(l),
1358            None => Err(LuaError::runtime(format_args!(
1359                "object length is not an integer"
1360            ))),
1361        }
1362    }
1363
1364    fn peek_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
1365        self.to_lua_string_bytes(idx)
1366    }
1367
1368    fn to_string_coerced(&mut self, idx: i32) -> Option<Vec<u8>> {
1369        self.to_lua_string_bytes(idx)
1370    }
1371
1372    fn raw_get(&mut self, idx: i32) -> Result<LuaType, LuaError> {
1373        Ok(lua_vm::api::raw_get(self, idx))
1374    }
1375
1376    fn raw_set(&mut self, idx: i32) -> Result<(), LuaError> {
1377        lua_vm::api::raw_set(self, idx)
1378    }
1379
1380    fn is_c_function_at(&mut self, idx: i32) -> bool {
1381        lua_vm::api::is_cfunction(self, idx)
1382    }
1383
1384    fn type_name_str_at(&mut self, idx: i32) -> &'static [u8] {
1385        let t = lua_vm::api::lua_type_at(self, idx);
1386        lua_vm::api::type_name(self, t)
1387    }
1388
1389    fn push_fstring(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), LuaError> {
1390        let formatted = std::fmt::format(args);
1391        lua_vm::api::push_fstring(self, formatted.as_bytes())?;
1392        Ok(())
1393    }
1394
1395    fn arith(&mut self, op: ArithOp) -> Result<(), LuaError> {
1396        lua_vm::api::arith(self, op as i32)
1397    }
1398
1399    fn lua_version(&mut self) -> f64 {
1400        504.0
1401    }
1402
1403    fn push_fail(&mut self) -> Result<(), LuaError> {
1404        self.push(LuaValue::Nil);
1405        Ok(())
1406    }
1407
1408    fn push_registry(&mut self) -> Result<(), LuaError> {
1409        let r = self.registry_value();
1410        self.push(r);
1411        Ok(())
1412    }
1413
1414    fn push_upvalue(&mut self, idx: i32) -> Result<(), LuaError> {
1415        lua_vm::api::push_value(self, upvalue_index(idx));
1416        Ok(())
1417    }
1418
1419    fn pop_bytes(&mut self) -> Vec<u8> {
1420        match self.pop() {
1421            LuaValue::Str(s) => s.as_bytes().to_vec(),
1422            _ => Vec::new(),
1423        }
1424    }
1425
1426    fn push_where(&mut self, level: i32) -> Result<(), LuaError> {
1427        let mut ar = lua_vm::debug::LuaDebug::default();
1428        if lua_vm::debug::get_stack(self, level, &mut ar) {
1429            lua_vm::debug::get_info(self, b"Sl", &mut ar);
1430            if ar.currentline > 0 {
1431                let zero = ar
1432                    .short_src
1433                    .iter()
1434                    .position(|&b| b == 0)
1435                    .unwrap_or(ar.short_src.len());
1436                let mut buf: Vec<u8> = ar.short_src[..zero].to_vec();
1437                buf.push(b':');
1438                buf.extend_from_slice(ar.currentline.to_string().as_bytes());
1439                buf.extend_from_slice(b": ");
1440                lua_vm::api::push_lstring(self, &buf)?;
1441                return Ok(());
1442            }
1443        }
1444        lua_vm::api::push_lstring(self, b"")?;
1445        Ok(())
1446    }
1447
1448    fn where_error(&mut self, level: i32, msg: &[u8]) -> LuaError {
1449        if self.push_where(level).is_err() {
1450            return LuaError::runtime(format_args!("{}", StubBStr(msg)));
1451        }
1452        let mut full = self.pop_bytes();
1453        full.extend_from_slice(msg);
1454        LuaError::runtime(format_args!("{}", StubBStr(&full)))
1455    }
1456
1457    fn registry_get(&mut self, key: &[u8]) -> Result<LuaType, LuaError> {
1458        lua_vm::api::get_field(self, STUB_LUA_REGISTRYINDEX, key)
1459    }
1460
1461    fn get_field_registry(&mut self, name: &[u8]) -> Result<LuaType, LuaError> {
1462        lua_vm::api::get_field(self, STUB_LUA_REGISTRYINDEX, name)
1463    }
1464
1465    fn get_registry_field(&mut self, name: &[u8]) -> Result<LuaType, LuaError> {
1466        lua_vm::api::get_field(self, STUB_LUA_REGISTRYINDEX, name)
1467    }
1468
1469    fn get_or_create_registry_subtable(&mut self, name: &[u8]) -> Result<bool, LuaError> {
1470        self.get_subtable_registry(name)
1471    }
1472
1473    fn registry_set(&mut self, key: &[u8]) -> Result<(), LuaError> {
1474        lua_vm::api::set_field(self, STUB_LUA_REGISTRYINDEX, key)
1475    }
1476
1477    fn check_stack_growth(&mut self, n: i32) -> bool {
1478        lua_vm::api::check_stack(self, n)
1479    }
1480
1481    fn ensure_stack<S: AsRef<[u8]> + ?Sized>(&mut self, n: i32, msg: &S) -> Result<(), LuaError> {
1482        if lua_vm::api::check_stack(self, n) {
1483            return Ok(());
1484        }
1485        let m = msg.as_ref();
1486        if m.is_empty() {
1487            Err(LuaError::runtime(format_args!("stack overflow")))
1488        } else {
1489            Err(LuaError::runtime(format_args!(
1490                "stack overflow ({})",
1491                StubBStr(m)
1492            )))
1493        }
1494    }
1495
1496    fn push_copy(&mut self, idx: i32) -> Result<(), LuaError> {
1497        lua_vm::api::push_value(self, idx);
1498        Ok(())
1499    }
1500
1501    fn as_bytes(&mut self, idx: i32) -> Option<Vec<u8>> {
1502        self.to_lua_string_bytes(idx)
1503    }
1504
1505    fn as_bytes_or_coerce(&mut self, idx: i32) -> Option<Vec<u8>> {
1506        self.to_lua_string_bytes(idx)
1507    }
1508
1509    fn thread_status(&mut self) -> LuaStatus {
1510        lua_vm::api::status(self)
1511    }
1512
1513    fn new_thread(&mut self, initial_body: Option<LuaValue>) -> Result<GcRef<LuaThread>, LuaError> {
1514        lua_vm::state::new_thread(self, initial_body)?;
1515        let th = lua_vm::api::to_thread(self, -1)
1516            .ok_or_else(|| LuaError::runtime(format_args!("new_thread: missing thread on top")))?;
1517        Ok(th)
1518    }
1519
1520    fn is_same_thread(&mut self, other: &LuaState) -> bool {
1521        std::ptr::eq(self as *const LuaState, other as *const LuaState)
1522    }
1523
1524    fn load_buffer(
1525        &mut self,
1526        buf: &[u8],
1527        name: &[u8],
1528        mode: Option<&[u8]>,
1529    ) -> Result<LuaStatus, LuaError> {
1530        let mut remaining = Some(buf.to_vec());
1531        let reader: Box<dyn FnMut() -> Option<Vec<u8>>> = Box::new(move || remaining.take());
1532        lua_vm::api::load(self, reader, Some(name), mode)
1533    }
1534
1535    fn load_buffer_ex<M: ?Sized>(
1536        &mut self,
1537        buf: &[u8],
1538        name: &[u8],
1539        mode: &M,
1540    ) -> Result<bool, LuaError>
1541    where
1542        M: AsRef<[u8]>,
1543    {
1544        let mut remaining = Some(buf.to_vec());
1545        let reader: Box<dyn FnMut() -> Option<Vec<u8>>> = Box::new(move || remaining.take());
1546        let mode_bytes = mode.as_ref();
1547        let status = lua_vm::api::load(self, reader, Some(name), Some(mode_bytes))?;
1548        Ok(status == LuaStatus::Ok)
1549    }
1550
1551    fn dump_function(&mut self, strip: bool) -> Result<Vec<u8>, LuaError> {
1552        let mut out: Vec<u8> = Vec::new();
1553        let mut writer = |chunk: &[u8]| -> Result<(), LuaError> {
1554            out.extend_from_slice(chunk);
1555            Ok(())
1556        };
1557        let ok = lua_vm::api::dump(self, &mut writer, strip)?;
1558        if !ok {
1559            return Err(LuaError::runtime(format_args!(
1560                "unable to dump given function"
1561            )));
1562        }
1563        Ok(out)
1564    }
1565
1566    fn warning(&mut self, msg: &[u8], to_cont: bool) -> Result<(), LuaError> {
1567        lua_vm::api::warning(self, msg, to_cont);
1568        Ok(())
1569    }
1570
1571    fn string_to_number(&mut self, idx: i32) -> Option<usize> {
1572        let bytes = lua_vm::api::to_lua_string(self, idx)
1573            .ok()
1574            .flatten()?
1575            .as_bytes()
1576            .to_vec();
1577        let consumed = lua_vm::api::string_to_number(self, &bytes);
1578        if consumed == 0 {
1579            None
1580        } else {
1581            Some(consumed)
1582        }
1583    }
1584
1585    fn string_to_number_push<S: AsRef<[u8]> + ?Sized>(&mut self, s: &S) -> Result<usize, LuaError> {
1586        Ok(lua_vm::api::string_to_number(self, s.as_ref()))
1587    }
1588
1589    fn gc_count(&mut self) -> Result<i32, LuaError> {
1590        Ok(lua_vm::api::gc(self, lua_vm::api::GcArgs::Count))
1591    }
1592
1593    fn gc_count_b(&mut self) -> Result<i32, LuaError> {
1594        Ok(lua_vm::api::gc(self, lua_vm::api::GcArgs::CountB))
1595    }
1596
1597    fn gc_step(&mut self, data: i32) -> Result<i32, LuaError> {
1598        Ok(lua_vm::api::gc(self, lua_vm::api::GcArgs::Step { data }))
1599    }
1600
1601    fn gc_is_running(&mut self) -> Result<bool, LuaError> {
1602        Ok(lua_vm::api::gc(self, lua_vm::api::GcArgs::IsRunning) != 0)
1603    }
1604
1605    fn gc_control_simple(&mut self, op: i32) -> Result<i32, LuaError> {
1606        let args = match op {
1607            0 => lua_vm::api::GcArgs::Stop,
1608            1 => lua_vm::api::GcArgs::Restart,
1609            2 => lua_vm::api::GcArgs::Collect,
1610            _ => return Err(LuaError::runtime(format_args!("invalid GC option {}", op))),
1611        };
1612        let res = lua_vm::api::gc(self, args);
1613        // 5.2/5.3 `collectgarbage("collect")` re-raises a `__gc` finalizer
1614        // error parked by the explicit-collect path (C `GCTM` propagation).
1615        if let Some(err) = self.global_mut().gc_finalizer_error.take() {
1616            return Err(LuaError::from_value(err));
1617        }
1618        Ok(res)
1619    }
1620
1621    fn gc_set_param(&mut self, op: i32, value: i32) -> Result<i32, LuaError> {
1622        let args = match op {
1623            6 => lua_vm::api::GcArgs::SetPause { value },
1624            7 => lua_vm::api::GcArgs::SetStepMul { value },
1625            _ => {
1626                return Err(LuaError::runtime(format_args!(
1627                    "invalid GC param option {}",
1628                    op
1629                )))
1630            }
1631        };
1632        Ok(lua_vm::api::gc(self, args))
1633    }
1634
1635    fn gc_gen(&mut self, minor_mul: i32, major_mul: i32) -> Result<i32, LuaError> {
1636        Ok(lua_vm::api::gc(
1637            self,
1638            lua_vm::api::GcArgs::Gen {
1639                minormul: minor_mul,
1640                majormul: major_mul,
1641            },
1642        ))
1643    }
1644
1645    fn gc_inc(&mut self, pause: i32, step_mul: i32, step_size: i32) -> Result<i32, LuaError> {
1646        Ok(lua_vm::api::gc(
1647            self,
1648            lua_vm::api::GcArgs::Inc {
1649                pause,
1650                stepmul: step_mul,
1651                stepsize: step_size,
1652            },
1653        ))
1654    }
1655
1656    fn gc_param(&mut self, param: usize, value: i64) -> Result<i64, LuaError> {
1657        Ok(lua_vm::api::gc(self, lua_vm::api::GcArgs::Param { param, value }) as i64)
1658    }
1659
1660    fn get_meta_field(&mut self, idx: i32, name: &[u8]) -> Result<bool, LuaError> {
1661        Ok(crate::auxlib::get_metafield(self, idx, name)? != LuaType::Nil)
1662    }
1663
1664    fn to_display_string(&mut self, idx: i32) -> Result<Vec<u8>, LuaError> {
1665        crate::auxlib::to_lua_string(self, idx)
1666    }
1667
1668    fn get_subtable_registry(&mut self, name: &[u8]) -> Result<bool, LuaError> {
1669        crate::auxlib::get_subtable(self, STUB_LUA_REGISTRYINDEX, name)
1670    }
1671
1672    fn new_metatable(&mut self, name: &[u8]) -> Result<bool, LuaError> {
1673        crate::auxlib::new_metatable(self, name)
1674    }
1675
1676    fn set_metatable_by_name(&mut self, name: &[u8]) -> Result<(), LuaError> {
1677        crate::auxlib::set_metatable(self, name)
1678    }
1679
1680    fn check_arg_userdata(
1681        &mut self,
1682        arg: i32,
1683        name: &[u8],
1684    ) -> Result<GcRef<LuaUserData>, LuaError> {
1685        crate::auxlib::check_udata(self, arg, name)
1686    }
1687
1688    fn test_arg_userdata(&mut self, arg: i32, name: &[u8]) -> Option<GcRef<LuaUserData>> {
1689        crate::auxlib::test_udata(self, arg, name).ok().flatten()
1690    }
1691
1692    fn get_table(&mut self, idx: i32) -> Result<LuaType, LuaError> {
1693        lua_vm::api::get_table(self, idx)
1694    }
1695
1696    fn get_stack(&mut self, level: i32, ar: &mut LuaDebug) -> bool {
1697        let mut lvm_ar = lua_vm::debug::LuaDebug::default();
1698        let ok = lua_vm::debug::get_stack(self, level, &mut lvm_ar);
1699        if ok {
1700            ar.i_ci_idx = lvm_ar.i_ci;
1701        } else {
1702            ar.i_ci_idx = None;
1703        }
1704        ok
1705    }
1706
1707    fn get_stack_level(&mut self, level: i32, ar: &mut LuaDebug) -> bool {
1708        LuaStateStubExt::get_stack(self, level, ar)
1709    }
1710
1711    fn get_info(&mut self, what: &[u8], ar: &mut LuaDebug) -> Result<(), LuaError> {
1712        let mut lvm_ar = lua_vm::debug::LuaDebug::default();
1713        lvm_ar.i_ci = ar.i_ci_idx;
1714        let ok = lua_vm::debug::get_info(self, what, &mut lvm_ar);
1715        copy_lvm_debug_to_stub_selective(&lvm_ar, ar, what);
1716        if ok {
1717            Ok(())
1718        } else {
1719            Err(LuaError::runtime(format_args!("invalid option")))
1720        }
1721    }
1722
1723    fn get_debug_info(&mut self, what: &[u8], ar: &mut LuaDebug) -> Result<(), LuaError> {
1724        LuaStateStubExt::get_info(self, what, ar)
1725    }
1726
1727    fn get_local_at(&mut self, ar: &LuaDebug, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
1728        let mut lvm_ar = lua_vm::debug::LuaDebug::default();
1729        lvm_ar.i_ci = ar.i_ci_idx;
1730        Ok(lua_vm::debug::get_local(self, Some(&lvm_ar), n))
1731    }
1732
1733    fn set_local_at(&mut self, ar: &LuaDebug, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
1734        let mut lvm_ar = lua_vm::debug::LuaDebug::default();
1735        lvm_ar.i_ci = ar.i_ci_idx;
1736        Ok(lua_vm::debug::set_local(self, &lvm_ar, n))
1737    }
1738
1739    fn get_param_name(&mut self, fidx: i32, n: i32) -> Result<Option<Vec<u8>>, LuaError> {
1740        let _ = fidx;
1741        Ok(lua_vm::debug::get_local(self, None, n))
1742    }
1743
1744    fn has_frames(&mut self) -> bool {
1745        !self.is_base_ci(self.current_ci_idx())
1746    }
1747
1748    fn lua_traceback(
1749        &mut self,
1750        other: &mut LuaState,
1751        msg: Option<&[u8]>,
1752        level: i32,
1753    ) -> Result<(), LuaError> {
1754        crate::auxlib::traceback(self, Some(other), msg, level)
1755    }
1756
1757    fn upvalue_id(&mut self, fidx: i32, n: i32) -> Result<*mut std::ffi::c_void, LuaError> {
1758        match lua_vm::api::upvalue_id(self, fidx, n) {
1759            Some(id) => Ok(id as *mut std::ffi::c_void),
1760            None => Ok(std::ptr::null_mut()),
1761        }
1762    }
1763
1764    fn join_upvalues(&mut self, fidx1: i32, n1: i32, fidx2: i32, n2: i32) -> Result<(), LuaError> {
1765        lua_vm::api::upvalue_join(self, fidx1, n1, fidx2, n2);
1766        Ok(())
1767    }
1768
1769    /// Pre-collect the chunks supplied by `reader` (a state-aware callback)
1770    /// and forward the accumulated buffer to `lua_vm::api::load`. The streaming
1771    /// loader in `lua_vm::api::load` consumes a `Box<dyn FnMut() -> Option<Vec<u8>>>`
1772    /// that does not take a `&mut LuaState`, so the state-touching reader
1773    /// (e.g. `generic_reader`, which calls a Lua function to produce each
1774    /// chunk) is drained first. C-Lua streams chunks directly through
1775    /// `lua_load`; the materialised path here is observable only for very
1776    /// large source files and is intentional for the Phase-B shim.
1777    fn load_with_reader<F, M: ?Sized>(
1778        &mut self,
1779        mut reader: F,
1780        name: &[u8],
1781        mode: &M,
1782    ) -> Result<bool, LuaError>
1783    where
1784        F: FnMut(&mut LuaState) -> Result<Option<Vec<u8>>, LuaError>,
1785        M: AsRef<[u8]>,
1786    {
1787        let mut buf: Vec<u8> = Vec::new();
1788        let mut reader_err: Option<LuaError> = None;
1789        loop {
1790            match reader(self) {
1791                Err(e) => {
1792                    reader_err = Some(e);
1793                    break;
1794                }
1795                Ok(None) => break,
1796                Ok(Some(piece)) => {
1797                    if piece.is_empty() {
1798                        break;
1799                    }
1800                    buf.extend_from_slice(&piece);
1801                }
1802            }
1803        }
1804        if let Some(e) = reader_err {
1805            let msg_value = match e {
1806                LuaError::Runtime(v) | LuaError::Syntax(v) => v,
1807                LuaError::Memory => {
1808                    let s = self.intern_str(b"not enough memory")?;
1809                    LuaValue::Str(s)
1810                }
1811                _ => {
1812                    let s = self.intern_str(b"error in reader function")?;
1813                    LuaValue::Str(s)
1814                }
1815            };
1816            self.push(msg_value);
1817            return Ok(false);
1818        }
1819        let mut once = Some(buf);
1820        let boxed: Box<dyn FnMut() -> Option<Vec<u8>>> = Box::new(move || once.take());
1821        let mode_bytes = mode.as_ref();
1822        let status = lua_vm::api::load(self, boxed, Some(name), Some(mode_bytes))?;
1823        Ok(status == LuaStatus::Ok)
1824    }
1825
1826    fn load_file_ex(&mut self, path: Option<&[u8]>, mode: Option<&[u8]>) -> Result<bool, LuaError> {
1827        let status = crate::auxlib::load_filex(self, path, mode)?;
1828        Ok(status == 0)
1829    }
1830
1831    fn load_file(&mut self, path: Option<&[u8]>) -> Result<bool, LuaError> {
1832        LuaStateStubExt::load_file_ex(self, path, None)
1833    }
1834
1835    fn get_iuservalue(&mut self, idx: i32, n: i32) -> Result<LuaType, LuaError> {
1836        Ok(lua_vm::api::get_i_uservalue(self, idx, n))
1837    }
1838
1839    fn set_iuservalue(&mut self, idx: i32, n: i32) -> Result<bool, LuaError> {
1840        lua_vm::api::set_i_uservalue(self, idx, n)
1841    }
1842
1843    fn get_hook_mask(&mut self) -> u32 {
1844        lua_vm::debug::get_hook_mask(self) as u32
1845    }
1846
1847    fn get_hook_count(&mut self) -> i32 {
1848        lua_vm::debug::get_hook_count(self)
1849    }
1850
1851    /// Approximate "is a debug hook installed?" using the hook event mask.
1852    /// `lua_sethook` clears the mask whenever the hook is uninstalled, so a
1853    /// non-zero mask is equivalent to a non-NULL `L->hook` for the
1854    /// `debug.gethook` call site. Avoids invoking `state.hook()`, which is
1855    /// still a Phase-B `todo!` on `LuaState`.
1856    fn hook_is_set(&mut self) -> bool {
1857        lua_vm::debug::get_hook_mask(self) != 0
1858    }
1859
1860    /// Hooks installed through the debug library use the Lua hook trampoline
1861    /// and store the real Lua callback in registry[HOOKKEY].
1862    fn hook_is_internal_lua_hook(&mut self) -> bool {
1863        lua_vm::debug::get_hook_mask(self) != 0
1864    }
1865
1866    fn set_c_stack_limit(&mut self, limit: i32) -> Result<i32, LuaError> {
1867        let clamped = if limit < 0 { 0u32 } else { limit as u32 };
1868        Ok(lua_vm::state::set_c_stack_limit(self, clamped))
1869    }
1870
1871    /// `lua_close(L)` destroys a Lua state. In Rust the state's resources are
1872    /// released by `Drop` when the owning value goes out of scope, so the
1873    /// in-place `&mut self` form is a no-op. The consuming free function
1874    /// `lua_vm::state::close(state)` is reserved for the top-level shutdown
1875    /// path in `lua-cli`.
1876    fn close(&mut self) {
1877        let _ = self;
1878    }
1879
1880    /// Install (or clear) a debug hook on this thread.
1881    ///
1882    /// (`ldebug.c`).
1883    ///
1884    /// The Phase-B `LuaStateStubExt` signature uses `lua_CFunction` (the
1885    /// stdlib C-function shape: `fn(&mut LuaState) -> Result<usize, LuaError>`)
1886    /// for `f`, whereas the canonical `lua_vm::debug::set_hook` takes a
1887    /// `Box<dyn FnMut(&mut LuaState, &LuaDebug)>` (a true Lua hook, which has
1888    /// access to the active `lua_Debug`). To bridge the two, an installed
1889    /// `lua_CFunction` is wrapped in a trampoline closure that calls it with
1890    /// `state` and discards both the activation record and the
1891    /// `Result<usize, LuaError>` (a hook's return value is ignored by C-Lua).
1892    fn set_hook_full(
1893        &mut self,
1894        f: Option<lua_CFunction>,
1895        mask: u32,
1896        count: i32,
1897    ) -> Result<(), LuaError> {
1898        let hook: Option<Box<dyn FnMut(&mut LuaState, &lua_vm::debug::LuaDebug)>> = match f {
1899            None => None,
1900            Some(func) => Some(Box::new(move |state, _ar| {
1901                let _ = func(state);
1902            })),
1903        };
1904        lua_vm::debug::set_hook(self, hook, mask as i32, count);
1905        Ok(())
1906    }
1907
1908    /// Write `msg` to the host's standard output stream.
1909    ///
1910    /// `fwrite(s, 1, l, stdout)`).
1911    ///
1912    /// Delegates to the canonical inherent `LuaState::write_output`. UFCS is
1913    /// used to disambiguate from the trait method (this method) which would
1914    /// otherwise recurse.
1915    fn write_output(&mut self, msg: &[u8]) -> Result<(), LuaError> {
1916        LuaState::write_output(self, msg)
1917    }
1918
1919    /// `t[n] = v`, where `t` is the value at `idx` and `v` is popped from the
1920    /// stack top. Honours `__newindex`.
1921    ///
1922    fn table_set_i(&mut self, idx: i32, n: i64) -> Result<(), LuaError> {
1923        LuaState::table_set_i(self, idx, n)
1924    }
1925
1926    /// Allocate a fresh full-userdata, push it on the stack, and return a
1927    /// `GcRef` to it. `name` is advisory (callers typically follow up with
1928    /// `set_metatable_by_name(name)`).
1929    ///
1930    /// C-correspondent: `lua_newuserdatauv(L, size, nuvalue)` plus the
1931    /// auxiliary `luaL_setmetatable` pattern. The Rust signature carries
1932    /// `name` for caller convenience as documented on the inherent method.
1933    fn new_userdata_typed(
1934        &mut self,
1935        name: &[u8],
1936        size: usize,
1937        nuvalue: i32,
1938    ) -> Result<GcRef<LuaUserData>, LuaError> {
1939        LuaState::new_userdata_typed(self, name, size, nuvalue)
1940    }
1941}
1942
1943/// Copy populated fields from the canonical `lua_vm::debug::LuaDebug` into
1944/// the Phase-B stub `LuaDebug`. The two structs diverge on a few field types
1945/// (e.g. `what` is a single byte tag in the stub vs. `Option<&'static [u8]>`
1946/// in the canonical struct, `short_src` is `Vec<u8>` vs. fixed array).
1947/// Copy only the fields that `lua_getinfo`'s `what` string actually populates
1948/// in C. Mirrors `auxgetinfo` in `ldebug.c`: each option byte writes a disjoint
1949/// subset of `lua_Debug`. Calling `get_info` with one option string must not
1950/// clobber fields populated by an earlier call with a different option string
1951/// (a pattern the auxiliary library relies on — `pushglobalfuncname` calls
1952/// `lua_getinfo(L, "f", ar)` and expects the previously-set `namewhat`/`what`/
1953/// `short_src`/`linedefined` to survive).
1954fn copy_lvm_debug_to_stub_selective(
1955    src: &lua_vm::debug::LuaDebug,
1956    dst: &mut LuaDebug,
1957    what: &[u8],
1958) {
1959    dst.i_ci_idx = src.i_ci;
1960    for &ch in what {
1961        match ch {
1962            b'S' => {
1963                dst.what = match src.what {
1964                    Some(b"Lua") => b'L',
1965                    Some(b"C") => b'C',
1966                    Some(b"main") => b'm',
1967                    _ => 0,
1968                };
1969                dst.source = src.source.clone().unwrap_or_default();
1970                let zero = src
1971                    .short_src
1972                    .iter()
1973                    .position(|&b| b == 0)
1974                    .unwrap_or(src.short_src.len());
1975                dst.short_src = src.short_src[..zero].to_vec();
1976                dst.linedefined = src.linedefined;
1977                dst.lastlinedefined = src.lastlinedefined;
1978            }
1979            b'l' => {
1980                dst.currentline = src.currentline;
1981            }
1982            b'u' => {
1983                dst.nups = src.nups;
1984                dst.nparams = src.nparams;
1985                dst.isvararg = src.isvararg;
1986            }
1987            b't' => {
1988                dst.istailcall = src.istailcall;
1989                dst.extraargs = src.extraargs;
1990            }
1991            b'n' => {
1992                dst.name = src.name.clone();
1993                dst.namewhat = src.namewhat.map(|s| s.to_vec()).unwrap_or_default();
1994            }
1995            b'r' => {
1996                dst.ftransfer = src.ftransfer;
1997                dst.ntransfer = src.ntransfer;
1998            }
1999            _ => {}
2000        }
2001    }
2002}
2003
2004const STUB_LUA_REGISTRYINDEX: i32 = -(1_000_000) - 1000;
2005
2006struct StubBStr<'a>(&'a [u8]);
2007
2008impl<'a> std::fmt::Display for StubBStr<'a> {
2009    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2010        use std::fmt::Write as _;
2011        for &b in self.0 {
2012            if b.is_ascii() {
2013                f.write_char(b as char)?;
2014            } else {
2015                write!(f, "\\x{:02x}", b)?;
2016            }
2017        }
2018        Ok(())
2019    }
2020}
2021
2022// ──────────────────────────────────────────────────────────────────────────
2023// PORT STATUS
2024//   source:        (Phase-B reconcile shim; no C source)
2025//   target_crate:  lua-stdlib
2026//   confidence:    high
2027//   todos:         0
2028//   port_notes:    3
2029//   unsafe_blocks: 0
2030//   notes:         Re-exports lua_vm::state::LuaState (canonical owner per
2031//                  harness/type-vocabulary.tsv); the LuaStateStubExt trait
2032//                  carries every Phase-A stub method as a
2033//                  todo!("phase-b-reconcile: …") body so the rest of
2034//                  lua-stdlib keeps compiling while the canonical API
2035//                  catches up.
2036// ──────────────────────────────────────────────────────────────────────────