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