1use crate::{
2 convert::{Index, ToLua},
3 error::Error,
4 ffi::*,
5 state::State,
6 str::*,
7};
8
9use alloc::borrow::Cow;
10use alloc::string::String;
11use alloc::vec::Vec;
12use core::ffi::{c_char, c_int, c_void};
13use core::{mem, ptr, slice, str};
14
15#[allow(non_camel_case_types)]
16type size_t = usize;
17
18#[extend::ext(pub, name = UnsafeLuaApi)]
19impl State {
20 fn new() -> *mut lua_State {
23 unsafe { luaL_newstate() }
24 }
25
26 #[inline(always)]
28 fn as_ptr(&self) -> *mut lua_State {
29 self.state
30 }
31
32 fn open_libs(&self) {
34 unsafe {
35 luaL_openlibs(self.state);
36 }
37 }
38
39 #[inline(always)]
41 fn open_base(&self) -> c_int {
42 unsafe { luaopen_base(self.state) }
43 }
44
45 #[inline(always)]
47 fn open_coroutine(&self) -> c_int {
48 unsafe { luaopen_coroutine(self.state) }
49 }
50
51 #[inline(always)]
53 fn open_table(&self) -> c_int {
54 unsafe { luaopen_table(self.state) }
55 }
56
57 #[inline(always)]
59 fn open_io(&self) -> c_int {
60 unsafe { luaopen_io(self.state) }
61 }
62
63 #[inline(always)]
65 fn open_os(&self) -> c_int {
66 unsafe { luaopen_os(self.state) }
67 }
68
69 #[inline(always)]
71 fn open_string(&self) -> c_int {
72 unsafe { luaopen_string(self.state) }
73 }
74
75 #[inline(always)]
77 fn open_utf8(&self) -> c_int {
78 unsafe { luaopen_utf8(self.state) }
79 }
80
81 #[inline(always)]
83 fn open_math(&self) -> c_int {
84 unsafe { luaopen_math(self.state) }
85 }
86
87 #[inline(always)]
89 fn open_debug(&self) -> c_int {
90 unsafe { luaopen_debug(self.state) }
91 }
92
93 #[inline(always)]
95 fn open_package(&self) -> c_int {
96 unsafe { luaopen_package(self.state) }
97 }
98
99 fn do_file(&self, filename: &str) -> i32 {
101 let c_str = CString::new(filename).unwrap();
102 unsafe { luaL_dofile(self.state, c_str.as_ptr()) }
103 }
104
105 fn do_string(&self, s: &str) -> i32 {
107 let c_str = CString::new(s).unwrap();
108 unsafe { luaL_dostring(self.state, c_str.as_ptr()) }
109 }
110
111 #[inline(always)]
116 fn close(&self) {
117 unsafe {
118 lua_close(self.state);
119 }
120 }
121
122 #[inline(always)]
124 fn new_thread(&self) -> *mut lua_State {
125 unsafe { lua_newthread(self.state) }
126 }
127
128 #[inline(always)]
130 fn at_panic(&self, panicf: lua_CFunction) -> lua_CFunction {
131 unsafe { lua_atpanic(self.state, panicf) }
132 }
133
134 fn version(state: *mut lua_State) -> lua_Number {
136 unsafe { lua_version(state) }
137 }
138
139 #[inline(always)]
144 fn abs_index(&self, idx: Index) -> Index {
145 unsafe { lua_absindex(self.state, idx) }
146 }
147
148 #[inline(always)]
150 fn get_top(&self) -> Index {
151 unsafe { lua_gettop(self.state) }
152 }
153
154 #[inline(always)]
156 fn set_top(&self, index: Index) {
157 unsafe { lua_settop(self.state, index) }
158 }
159
160 #[inline(always)]
162 fn rotate(&self, idx: Index, n: c_int) {
163 unsafe { lua_rotate(self.state, idx, n) }
164 }
165
166 #[inline(always)]
168 fn copy(&self, from_idx: Index, to_idx: Index) {
169 unsafe { lua_copy(self.state, from_idx, to_idx) }
170 }
171
172 #[inline(always)]
174 fn check_stack(&self, extra: c_int) -> bool {
175 let result = unsafe { lua_checkstack(self.state, extra) };
176 result != 0
177 }
178
179 #[inline(always)]
181 fn xmove(&self, to: *mut lua_State, n: c_int) {
182 unsafe { lua_xmove(self.state, to, n) }
183 }
184
185 #[inline(always)]
190 fn is_number(&self, index: Index) -> bool {
191 unsafe { lua_isnumber(self.state, index) == 1 }
192 }
193
194 #[inline(always)]
196 fn is_string(&self, index: Index) -> bool {
197 unsafe { lua_isstring(self.state, index) == 1 }
198 }
199
200 #[inline(always)]
202 fn is_native_fn(&self, index: Index) -> bool {
203 unsafe { lua_iscfunction(self.state, index) == 1 }
204 }
205
206 #[inline(always)]
208 fn is_integer(&self, index: Index) -> bool {
209 unsafe { lua_isinteger(self.state, index) == 1 }
210 }
211
212 #[inline(always)]
214 fn is_userdata(&self, index: Index) -> bool {
215 unsafe { lua_isuserdata(self.state, index) == 1 }
216 }
217
218 #[inline(always)]
220 fn type_of(&self, index: Index) -> Type {
221 let result = unsafe { lua_type(self.state, index) };
222 Type::from_c_int(result)
223 }
224
225 #[inline(always)]
227 fn typename_of(&self, tp: Type) -> Cow<str> {
228 unsafe {
229 let ptr = lua_typename(self.state, tp as c_int);
230 let slice = CStr::from_ptr(ptr).to_bytes();
231 String::from_utf8_lossy(slice)
232 }
233 }
234
235 #[inline(always)]
237 fn to_bool(&self, index: Index) -> bool {
238 let result = unsafe { lua_toboolean(self.state, index) };
239 result != 0
240 }
241
242 #[inline(always)]
246 fn raw_len(&self, index: Index) -> size_t {
247 unsafe { lua_rawlen(self.state, index) as _ }
248 }
249
250 #[inline(always)]
252 fn to_native_fn(&self, index: Index) -> lua_CFunction {
253 let result = unsafe { lua_tocfunction(self.state, index) };
254 result
255 }
256
257 #[inline(always)]
259 fn to_userdata(&self, index: Index) -> *mut c_void {
260 unsafe { lua_touserdata(self.state, index) }
261 }
262
263 #[inline]
265 fn to_thread(&self, index: Index) -> Option<&mut lua_State> {
266 unsafe { lua_tothread(self.state, index).as_mut() }
267 }
268
269 #[inline(always)]
271 fn to_pointer(&self, index: Index) -> *const c_void {
272 unsafe { lua_topointer(self.state, index) }
273 }
274
275 #[inline(always)]
280 fn arith(&self, op: Arithmetic) {
281 unsafe { lua_arith(self.state, op as c_int) }
282 }
283
284 #[inline(always)]
286 fn raw_equal(&self, idx1: Index, idx2: Index) -> bool {
287 let result = unsafe { lua_rawequal(self.state, idx1, idx2) };
288 result != 0
289 }
290
291 #[inline(always)]
293 fn compare(&self, idx1: Index, idx2: Index, op: Comparison) -> bool {
294 let result = unsafe { lua_compare(self.state, idx1, idx2, op as c_int) };
295 result != 0
296 }
297
298 #[inline(always)]
303 fn push_nil(&self) {
304 unsafe { lua_pushnil(self.state) }
305 }
306
307 #[inline(always)]
309 fn push_number(&self, n: lua_Number) {
310 unsafe { lua_pushnumber(self.state, n) }
311 }
312
313 #[inline(always)]
315 fn push_integer(&self, i: lua_Integer) {
316 unsafe { lua_pushinteger(self.state, i) }
317 }
318
319 #[inline(always)]
323 fn push_string(&self, s: &str) {
324 unsafe { lua_pushlstring(self.state, s.as_ptr() as *const _, s.len() as size_t) };
325 }
326
327 #[inline(always)]
329 fn push_bytes(&self, s: &[u8]) {
330 unsafe { lua_pushlstring(self.state, s.as_ptr() as *const _, s.len() as size_t) };
331 }
332
333 #[inline(always)]
338 fn push_cclosure(&self, f: lua_CFunction, n: c_int) {
339 unsafe { lua_pushcclosure(self.state, f, n) }
340 }
341
342 #[inline(always)]
344 fn push_bool(&self, b: bool) {
345 unsafe { lua_pushboolean(self.state, b as c_int) }
346 }
347
348 #[inline(always)]
353 fn push_light_userdata<T>(&self, ud: *mut T) {
354 unsafe { lua_pushlightuserdata(self.state, mem::transmute(ud)) }
355 }
356
357 #[inline(always)]
359 fn push_thread(&self) -> bool {
360 let result = unsafe { lua_pushthread(self.state) };
361 result != 1
362 }
363
364 #[inline(always)]
366 fn push_value(&self, index: Index) {
367 unsafe { lua_pushvalue(self.state, index) }
368 }
369
370 #[inline(always)]
375 fn get_global(&self, name: &CStr) -> Type {
376 Type::from_c_int(unsafe { lua_getglobal(self.state, name.as_ptr()) })
377 }
378
379 #[inline(always)]
381 fn get_table(&self, index: Index) -> Type {
382 let ty = unsafe { lua_gettable(self.state, index) };
383 Type::from_c_int(ty)
384 }
385
386 #[inline(always)]
388 fn get_field(&self, index: Index, k: &CStr) -> Type {
389 Type::from_c_int(unsafe { lua_getfield(self.state, index, k.as_ptr()) })
390 }
391
392 #[inline(always)]
394 fn geti(&self, index: Index, i: lua_Integer) -> Type {
395 let ty = unsafe { lua_geti(self.state, index, i) };
396 Type::from_c_int(ty)
397 }
398
399 #[inline(always)]
401 fn raw_get(&self, index: Index) -> Type {
402 let ty = unsafe { lua_rawget(self.state, index) };
403 Type::from_c_int(ty)
404 }
405
406 #[inline(always)]
408 fn raw_geti(&self, index: Index, n: lua_Integer) -> Type {
409 let ty = unsafe { lua_rawgeti(self.state, index, n) };
410 Type::from_c_int(ty)
411 }
412
413 #[inline(always)]
415 fn raw_getp<T>(&self, index: Index, p: *const T) -> Type {
416 let ty = unsafe { lua_rawgetp(self.state, index, mem::transmute(p)) };
417 Type::from_c_int(ty)
418 }
419
420 #[inline(always)]
422 fn create_table(&self, narr: c_int, nrec: c_int) {
423 unsafe { lua_createtable(self.state, narr, nrec) }
424 }
425
426 #[inline(always)]
430 fn new_userdata(&self, sz: size_t) -> *mut c_void {
431 unsafe { lua_newuserdata(self.state, sz) }
432 }
433
434 #[inline(always)]
435 fn new_userdatauv(&self, sz: size_t, n: i32) -> *mut c_void {
436 unsafe { lua_newuserdatauv(self.state, sz, n) }
437 }
438
439 #[inline(always)]
441 fn get_metatable(&self, objindex: Index) -> bool {
442 let result = unsafe { lua_getmetatable(self.state, objindex) };
443 result != 0
444 }
445
446 #[inline(always)]
448 fn get_uservalue(&self, idx: Index) -> Type {
449 let result = unsafe { lua_getuservalue(self.state, idx) };
450 Type::from_c_int(result)
451 }
452
453 #[inline(always)]
455 fn get_iuservalue(&self, idx: Index, n: i32) -> Type {
456 let result = unsafe { lua_getiuservalue(self.state, idx, n) };
457 Type::from_c_int(result)
458 }
459
460 #[inline(always)]
465 fn set_global(&self, var: &CStr) {
466 unsafe { lua_setglobal(self.state, var.as_ptr()) }
467 }
468
469 #[inline(always)]
471 fn set_table(&self, idx: Index) {
472 unsafe { lua_settable(self.state, idx) }
473 }
474
475 #[inline(always)]
477 fn set_field(&self, idx: Index, k: &CStr) {
478 unsafe { lua_setfield(self.state, idx, k.as_ptr()) }
479 }
480
481 #[inline(always)]
483 fn seti(&self, idx: Index, n: lua_Integer) {
484 unsafe { lua_seti(self.state, idx, n) }
485 }
486
487 #[inline(always)]
489 fn raw_set(&self, idx: Index) {
490 unsafe { lua_rawset(self.state, idx) }
491 }
492
493 #[inline(always)]
495 fn raw_seti(&self, idx: Index, n: lua_Integer) {
496 unsafe { lua_rawseti(self.state, idx, n) }
497 }
498
499 #[inline(always)]
501 fn raw_setp<T>(&self, idx: Index, p: *const T) {
502 unsafe { lua_rawsetp(self.state, idx, mem::transmute(p)) }
503 }
504
505 #[inline(always)]
507 fn set_metatable(&self, objindex: Index) {
508 unsafe { lua_setmetatable(self.state, objindex) };
509 }
510
511 #[inline(always)]
513 fn set_uservalue(&self, idx: Index) {
514 unsafe {
515 lua_setuservalue(self.state, idx);
516 }
517 }
518
519 #[inline(always)]
521 fn set_iuservalue(&self, idx: Index, n: i32) {
522 unsafe {
523 lua_setiuservalue(self.state, idx, n);
524 }
525 }
526
527 #[inline(always)]
529 fn call(&self, n: c_int, r: c_int) {
530 unsafe { lua_call(self.state, n, r) }
531 }
532
533 fn tailcall(self, n: c_int, r: c_int) {
534 let state = self.state;
535 drop(self);
536 unsafe { lua_call(state, n, r) }
537 }
538
539 fn resume(&self, from: *mut lua_State, nargs: c_int, nresults: &mut c_int) -> ThreadStatus {
544 let result = unsafe { lua_resume(self.state, from, nargs, nresults) };
545 ThreadStatus::from_c_int(result)
546 }
547
548 #[inline(always)]
550 fn status(&self) -> ThreadStatus {
551 let result = unsafe { lua_status(self.state) };
552 ThreadStatus::from_c_int(result)
553 }
554
555 #[inline(always)]
557 fn is_yieldable(&self) -> bool {
558 let result = unsafe { lua_isyieldable(self.state) };
559 result != 0
560 }
561
562 #[inline(always)]
568 fn gc(&self, what: GcOption, data: c_int) -> c_int {
569 unsafe { lua_gc(self.state, what as c_int, data) }
570 }
571
572 #[inline(always)]
577 fn error(self) -> ! {
578 let state = self.state;
579 drop(self);
580 unsafe { lua_error(state) };
581 }
582
583 #[inline(always)]
585 fn next(&self, idx: Index) -> bool {
586 let result = unsafe { lua_next(self.state, idx) };
587 result != 0
588 }
589
590 #[inline(always)]
592 fn concat(&self, n: c_int) {
593 unsafe { lua_concat(self.state, n) }
594 }
595
596 #[inline(always)]
598 fn len(&self, idx: Index) {
599 unsafe { lua_len(self.state, idx) }
600 }
601
602 fn string_to_number(&self, s: &str) -> size_t {
604 let c_str = CString::new(s).unwrap();
605 unsafe { lua_stringtonumber(self.state, c_str.as_ptr()) }
606 }
607
608 #[inline(always)]
610 fn get_alloc_fn(&self) -> (lua_Alloc, *mut c_void) {
611 let mut slot = ptr::null_mut();
612 (unsafe { lua_getallocf(self.state, &mut slot) }, slot)
613 }
614
615 #[inline(always)]
617 fn set_alloc_fn(&self, f: lua_Alloc, ud: *mut c_void) {
618 unsafe { lua_setallocf(self.state, f, ud) }
619 }
620
621 #[inline(always)]
623 fn to_number(&self, index: Index) -> lua_Number {
624 unsafe { lua_tonumber(self.state, index) }
625 }
626
627 #[inline(always)]
629 fn to_numberx(&self, index: Index) -> Option<lua_Number> {
630 let mut suc = 0i32;
631 let r = unsafe { lua_tonumberx(self.state, index, &mut suc) };
632 if suc > 0 {
633 Some(r)
634 } else {
635 None
636 }
637 }
638
639 #[inline(always)]
641 fn to_integer(&self, index: Index) -> lua_Integer {
642 unsafe { lua_tointeger(self.state, index) }
643 }
644
645 #[inline(always)]
647 fn to_integerx(&self, index: Index) -> Option<lua_Integer> {
648 let mut isnum: c_int = 0;
649 let r = unsafe { lua_tointegerx(self.state, index, &mut isnum) };
650 if isnum == 0 {
651 None
652 } else {
653 Some(r)
654 }
655 }
656
657 #[inline(always)]
659 fn pop(&self, n: c_int) {
660 unsafe { lua_pop(self.state, n) }
661 }
662
663 #[inline(always)]
665 fn new_table(&self) {
666 unsafe { lua_newtable(self.state) }
667 }
668
669 #[inline(always)]
671 fn register(&self, n: &str, f: CFunction) {
672 let c_str = CString::new(n).unwrap();
673 unsafe { lua_register(self.state, c_str.as_ptr(), Some(f)) }
674 }
675
676 #[inline(always)]
678 fn push_fn(&self, f: lua_CFunction) {
679 unsafe { lua_pushcfunction(self.state, f) }
680 }
681
682 #[inline(always)]
684 fn is_function(&self, index: Index) -> bool {
685 unsafe { lua_isfunction(self.state, index) == 1 }
686 }
687
688 #[inline(always)]
690 fn is_table(&self, index: Index) -> bool {
691 unsafe { lua_istable(self.state, index) == 1 }
692 }
693
694 #[inline(always)]
696 fn is_light_userdata(&self, index: Index) -> bool {
697 unsafe { lua_islightuserdata(self.state, index) == 1 }
698 }
699
700 #[inline(always)]
702 fn is_nil(&self, index: Index) -> bool {
703 unsafe { lua_isnil(self.state, index) == 1 }
704 }
705
706 #[inline(always)]
708 fn is_bool(&self, index: Index) -> bool {
709 unsafe { lua_isboolean(self.state, index) == 1 }
710 }
711
712 #[inline(always)]
714 fn is_thread(&self, index: Index) -> bool {
715 unsafe { lua_isthread(self.state, index) == 1 }
716 }
717
718 #[inline(always)]
720 fn is_none(&self, index: Index) -> bool {
721 unsafe { lua_isnone(self.state, index) == 1 }
722 }
723
724 #[inline(always)]
726 fn is_none_or_nil(&self, index: Index) -> bool {
727 unsafe { lua_isnoneornil(self.state, index) == 1 }
728 }
729
730 #[inline(always)]
734 fn push_global_table(&self) {
735 unsafe { lua_pushglobaltable(self.state) };
736 }
737
738 #[inline(always)]
740 fn insert(&self, idx: Index) {
741 unsafe { lua_insert(self.state, idx) }
742 }
743
744 #[inline(always)]
746 fn remove(&self, idx: Index) {
747 unsafe { lua_remove(self.state, idx) }
748 }
749
750 #[inline(always)]
752 fn replace(&self, idx: Index) {
753 unsafe { lua_replace(self.state, idx) }
754 }
755
756 fn get_stack(&self, level: c_int) -> Option<lua_Debug> {
761 let mut ar: lua_Debug = unsafe { core::mem::zeroed() };
762 let result = unsafe { lua_getstack(self.state, level, &mut ar) };
763 if result == 1 {
764 Some(ar)
765 } else {
766 None
767 }
768 }
769
770 fn get_info(&self, what: &CStr, ar: &mut lua_Debug) -> i32 {
772 unsafe { lua_getinfo(self.state, what.as_ptr(), ar) }
773 }
774
775 fn get_local(&self, ar: &lua_Debug, n: c_int) -> Option<&str> {
777 let ptr = unsafe { lua_getlocal(self.state, ar, n) };
778 if ptr.is_null() {
779 None
780 } else {
781 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
782 str::from_utf8(slice).ok()
783 }
784 }
785
786 fn set_local(&self, ar: &lua_Debug, n: c_int) -> Option<&str> {
788 let ptr = unsafe { lua_setlocal(self.state, ar, n) };
789 if ptr.is_null() {
790 None
791 } else {
792 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
793 str::from_utf8(slice).ok()
794 }
795 }
796
797 fn get_upvalue(&self, funcindex: Index, n: c_int) -> Option<&str> {
799 let ptr = unsafe { lua_getupvalue(self.state, funcindex, n) };
800 if ptr.is_null() {
801 None
802 } else {
803 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
804 str::from_utf8(slice).ok()
805 }
806 }
807
808 fn set_upvalue(&self, funcindex: Index, n: c_int) -> Option<&str> {
810 let ptr = unsafe { lua_setupvalue(self.state, funcindex, n) };
811 if ptr.is_null() {
812 None
813 } else {
814 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
815 str::from_utf8(slice).ok()
816 }
817 }
818
819 fn upvalue_id(&self, funcindex: Index, n: c_int) -> *mut c_void {
821 unsafe { lua_upvalueid(self.state, funcindex, n) }
822 }
823
824 fn upvalue_join(&self, fidx1: Index, n1: c_int, fidx2: Index, n2: c_int) {
826 unsafe { lua_upvaluejoin(self.state, fidx1, n1, fidx2, n2) }
827 }
828
829 #[cfg(feature = "std")]
830 fn set_hook(&self, func: Option<lua_Hook>, mask: HookMask, count: c_int) {
832 unsafe { lua_sethook(self.state, func, mask.bits(), count) }
833 }
834
835 fn get_hook(&self) -> Option<lua_Hook> {
837 unsafe { lua_gethook(self.state) }
838 }
839
840 #[cfg(feature = "std")]
841 fn get_hook_mask(&self) -> HookMask {
843 let result = unsafe { lua_gethookmask(self.state) };
844 HookMask::from_bits_truncate(result)
845 }
846
847 fn get_hook_count(&self) -> c_int {
849 unsafe { lua_gethookcount(self.state) }
850 }
851
852 #[inline(always)]
854 fn get_metafield(&self, obj: Index, e: &CStr) -> bool {
855 let result = unsafe { luaL_getmetafield(self.state, obj, e.as_ptr()) };
856 result != 0
857 }
858
859 #[inline(always)]
861 fn call_meta(&self, obj: Index, e: &CStr) -> bool {
862 let result = unsafe { luaL_callmeta(self.state, obj, e.as_ptr()) };
863 result != 0
864 }
865
866 #[inline(always)]
868 fn to_string(&self, index: Index) -> *const c_char {
869 unsafe { lua_tolstring(self.state, index, ptr::null_mut()) }
870 }
871
872 #[inline(always)]
874 fn tolstring(&self, index: Index, size: &mut usize) -> *const c_char {
875 unsafe { lua_tolstring(self.state, index, size as *mut usize) }
876 }
877
878 #[inline(always)]
880 fn to_cfunction(&self, index: Index) -> lua_CFunction {
881 unsafe { lua_tocfunction(self.state, index) }
882 }
883
884 #[inline(always)]
887 fn cast_string(&self, index: Index) -> Option<&[u8]> {
888 let mut len = 0;
889 let ptr = unsafe { luaL_tolstring(self.state, index, &mut len) };
890 if ptr.is_null() {
891 None
892 } else {
893 Some(unsafe { slice::from_raw_parts(ptr as *const u8, len as usize) })
894 }
895 }
896
897 #[inline(always)]
898 fn to_str<'a>(&'a self, index: Index) -> Option<&'a str> {
899 self.to_bytes(index).and_then(|r| str::from_utf8(r).ok())
900 }
901
902 #[inline(always)]
903 fn to_string_lossy<'a>(&'a self, index: Index) -> Option<Cow<'a, str>> {
904 self.to_bytes(index).map(|r| String::from_utf8_lossy(r))
905 }
906
907 fn to_bytes(&self, index: Index) -> Option<&[u8]> {
911 let mut len = 0;
912 let ptr = unsafe { lua_tolstring(self.state, index, &mut len) };
913 if ptr.is_null() {
914 None
915 } else {
916 Some(unsafe { slice::from_raw_parts(ptr as *const u8, len as usize) })
917 }
918 }
919
920 fn arg_error(&self, arg: Index, extramsg: &CStr) -> ! {
922 unsafe { luaL_argerror(self.state, arg, extramsg.as_ptr()) };
923 unreachable!()
924 }
925
926 #[inline(always)]
928 fn check_number(&self, arg: Index) -> lua_Number {
929 unsafe { luaL_checknumber(self.state, arg) }
930 }
931
932 #[inline(always)]
934 fn opt_number(&self, arg: Index, def: lua_Number) -> lua_Number {
935 unsafe { luaL_optnumber(self.state, arg, def) }
936 }
937
938 #[inline(always)]
940 fn check_integer(&self, arg: Index) -> lua_Integer {
941 unsafe { luaL_checkinteger(self.state, arg) }
942 }
943
944 #[inline(always)]
946 fn opt_integer(&self, arg: Index, def: lua_Integer) -> lua_Integer {
947 unsafe { luaL_optinteger(self.state, arg, def) }
948 }
949
950 fn check_stack_msg(&self, sz: c_int, msg: &str) {
952 let c_str = CString::new(msg).unwrap();
953 unsafe { luaL_checkstack(self.state, sz, c_str.as_ptr()) }
954 }
955
956 #[inline(always)]
958 fn check_type(&self, arg: Index, t: Type) {
959 unsafe { luaL_checktype(self.state, arg, t as c_int) }
960 }
961
962 #[inline(always)]
964 fn check_any(&self, arg: Index) {
965 unsafe { luaL_checkany(self.state, arg) }
966 }
967
968 #[inline(always)]
970 fn new_metatable(&self, tname: &CStr) -> bool {
971 unsafe { luaL_newmetatable(self.state, tname.as_ptr()) != 0 }
972 }
973
974 #[inline(always)]
976 fn set_metatable_from_registry(&self, tname: &CStr) {
977 unsafe { luaL_setmetatable(self.state, tname.as_ptr()) }
978 }
979
980 #[inline(always)]
982 fn test_userdata(&self, arg: Index, tname: &CStr) -> *mut c_void {
983 unsafe { luaL_testudata(self.state, arg, tname.as_ptr()) }
984 }
985
986 #[inline(always)]
989 unsafe fn test_userdata_typed<'a, T>(
990 &'a mut self,
991 arg: Index,
992 tname: &CStr,
993 ) -> Option<&'a mut T> {
994 mem::transmute(self.test_userdata(arg, tname))
995 }
996
997 #[inline(always)]
999 fn checkudata<'a, T>(&'a self, arg: Index, tname: &CStr) -> &'a mut T {
1000 unsafe { mem::transmute(luaL_checkudata(self.state, arg, tname.as_ptr())) }
1001 }
1002
1003 #[inline(always)]
1005 fn location(&self, lvl: c_int) {
1006 unsafe { luaL_where(self.state, lvl) }
1007 }
1008
1009 fn check_option(&self, arg: Index, def: Option<&str>, lst: &[&str]) -> usize {
1013 let mut vec: Vec<*const c_char> = Vec::with_capacity(lst.len() + 1);
1014 let cstrs: Vec<CString> = lst.iter().map(|ent| CString::new(*ent).unwrap()).collect();
1015 for ent in cstrs.iter() {
1016 vec.push(ent.as_ptr());
1017 }
1018 vec.push(ptr::null());
1019 let result = match def {
1020 Some(def) => unsafe {
1021 let c_str = CString::new(def).unwrap();
1022 luaL_checkoption(self.state, arg, c_str.as_ptr(), vec.as_ptr())
1023 },
1024 None => unsafe { luaL_checkoption(self.state, arg, ptr::null(), vec.as_ptr()) },
1025 };
1026 result as usize
1027 }
1028
1029 #[inline(always)]
1031 fn reference(&self, t: Index) -> Reference {
1032 let result = unsafe { luaL_ref(self.state, t) };
1033 Reference(result)
1034 }
1035
1036 #[inline(always)]
1038 fn unreference(&self, t: Index, reference: Reference) {
1039 unsafe { luaL_unref(self.state, t, reference.value()) }
1040 }
1041
1042 fn load_filex(&self, filename: &str, mode: &str) -> i32 {
1044 unsafe {
1045 let filename_c_str = CString::new(filename).unwrap();
1046 let mode_c_str = CString::new(mode).unwrap();
1047 luaL_loadfilex(self.state, filename_c_str.as_ptr(), mode_c_str.as_ptr())
1048 }
1049 }
1050
1051 fn load_file(&self, filename: &str) -> i32 {
1053 let c_str = CString::new(filename).unwrap();
1054 unsafe { luaL_loadfile(self.state, c_str.as_ptr()) }
1055 }
1056
1057 fn load_buffer<F: AsRef<[u8]>>(&self, source: F, chunk_name: Option<&str>) -> i32 {
1059 let buffer = source.as_ref();
1060 let chunk = chunk_name.and_then(|name| CString::new(name).ok());
1061 unsafe {
1062 luaL_loadbuffer(
1063 self.state,
1064 buffer.as_ptr() as *const c_char,
1065 buffer.len(),
1066 chunk.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()),
1067 )
1068 }
1069 }
1070
1071 fn load_bufferx(&self, buff: &[u8], name: &str, mode: &str) -> i32 {
1073 let name_c_str = CString::new(name).unwrap();
1074 let mode_c_str = CString::new(mode).unwrap();
1075 unsafe {
1076 luaL_loadbufferx(
1077 self.state,
1078 buff.as_ptr() as *const _,
1079 buff.len() as size_t,
1080 name_c_str.as_ptr(),
1081 mode_c_str.as_ptr(),
1082 )
1083 }
1084 }
1085
1086 fn load_string(&self, source: &str) -> i32 {
1088 let c_str = CString::new(source).unwrap();
1089 unsafe { luaL_loadstring(self.state, c_str.as_ptr()) }
1090 }
1091
1092 #[inline]
1094 fn dump(&self, mut writer: impl FnMut(&[u8]), strip: bool) -> c_int {
1095 use core::mem::transmute;
1096 unsafe extern "C-unwind" fn dump_wrapper(
1097 l: *mut lua_State,
1098 p: *const c_void,
1099 sz: usize,
1100 ud: *mut c_void,
1101 ) -> c_int {
1102 let callback = transmute::<_, &mut &mut dyn FnMut(&[u8])>(ud);
1103 callback(core::slice::from_raw_parts(p as *const u8, sz));
1104 0
1105 }
1106 let writer: &mut dyn FnMut(&[u8]) = &mut writer;
1107 unsafe { lua_dump(self.state, dump_wrapper, transmute(&writer), strip as c_int) }
1108 }
1109
1110 fn len_direct(&self, index: Index) -> lua_Integer {
1112 unsafe { luaL_len(self.state, index) }
1113 }
1114
1115 fn gsub(&self, s: &str, p: &str, r: &str) -> &str {
1117 let s_c_str = CString::new(s).unwrap();
1118 let p_c_str = CString::new(p).unwrap();
1119 let r_c_str = CString::new(r).unwrap();
1120 let ptr = unsafe {
1121 luaL_gsub(
1122 self.state,
1123 s_c_str.as_ptr(),
1124 p_c_str.as_ptr(),
1125 r_c_str.as_ptr(),
1126 )
1127 };
1128 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
1129 str::from_utf8(slice).unwrap()
1130 }
1131
1132 fn set_fns(&self, l: &[(&str, lua_CFunction)], nup: c_int) {
1134 let mut reg: Vec<luaL_Reg> = Vec::with_capacity(l.len() + 1);
1135 let ents: Vec<(CString, lua_CFunction)> = l
1136 .iter()
1137 .map(|&(s, f)| (CString::new(s).unwrap(), f))
1138 .collect();
1139 for &(ref s, f) in ents.iter() {
1140 reg.push(luaL_Reg {
1141 name: s.as_ptr(),
1142 func: f,
1143 });
1144 }
1145 reg.push(luaL_Reg {
1146 name: ptr::null(),
1147 func: None,
1148 });
1149 unsafe { luaL_setfuncs(self.state, reg.as_ptr(), nup) }
1150 }
1151
1152 #[inline(always)]
1154 fn get_subtable(&self, idx: Index, fname: &CStr) -> bool {
1155 unsafe { luaL_getsubtable(self.state, idx, fname.as_ptr()) != 0 }
1156 }
1157
1158 #[inline(always)]
1160 fn traceback(&self, state: *mut lua_State, msg: &CStr, level: c_int) {
1161 unsafe { luaL_traceback(self.state, state, msg.as_ptr(), level) }
1162 }
1163
1164 #[inline(always)]
1166 fn requiref(&self, modname: &CStr, openf: CFunction, glb: bool) {
1167 unsafe { luaL_requiref(self.state, modname.as_ptr(), Some(openf), glb as c_int) }
1168 }
1169
1170 #[inline(always)]
1172 fn arg_check(&self, cond: bool, arg: Index, extramsg: &str) {
1173 let c_str = CString::new(extramsg).unwrap();
1174 unsafe { luaL_argcheck(self.state, cond as c_int, arg, c_str.as_ptr()) }
1175 }
1176
1177 fn check_string(&self, n: Index) -> &str {
1179 let mut size = 0;
1180 let ptr = unsafe { luaL_checklstring(self.state, n, &mut size) };
1181 let slice = unsafe { slice::from_raw_parts(ptr as *const u8, size as usize) };
1182 str::from_utf8(slice).unwrap()
1183 }
1184
1185 fn opt_string<'a>(&'a mut self, n: Index, default: &'a str) -> &'a str {
1187 let mut size = 0;
1188 let c_str = CString::new(default).unwrap();
1189 let ptr = unsafe { luaL_optlstring(self.state, n, c_str.as_ptr(), &mut size) };
1190 if ptr == c_str.as_ptr() {
1191 default
1192 } else {
1193 let slice = unsafe { slice::from_raw_parts(ptr as *const u8, size as usize) };
1194 str::from_utf8(slice).unwrap()
1195 }
1196 }
1197
1198 #[inline(always)]
1200 fn get_metatable_from_registry(&self, tname: &str) {
1201 let c_str = CString::new(tname).unwrap();
1202 unsafe { luaL_getmetatable(self.state, c_str.as_ptr()) }
1203 }
1204
1205 #[inline(always)]
1207 fn push<T: ToLua>(&self, value: T) -> Result<(), Error> {
1208 match T::__PUSH {
1209 Some(push) => {
1210 #[cfg(debug_assertions)]
1211 let top = self.get_top();
1212 push(value, self)?;
1213 #[cfg(debug_assertions)]
1214 assert_eq!(top + 1, self.get_top(), "{}", core::any::type_name::<T>());
1215 }
1216 None => {
1217 let top = self.get_top();
1218 self.push_value(value.to_lua(self)?.index);
1219 if !self.clear_with_keep_top_one(top) {
1220 panic!(
1221 "stack should be increased, top: {top} after: {}",
1222 self.get_top()
1223 );
1224 }
1225 }
1226 }
1227 Ok(())
1228 }
1229}
1230
1231#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1233pub enum Arithmetic {
1234 Add = LUA_OPADD as isize,
1235 Sub = LUA_OPSUB as isize,
1236 Mul = LUA_OPMUL as isize,
1237 Mod = LUA_OPMOD as isize,
1238 Pow = LUA_OPPOW as isize,
1239 Div = LUA_OPDIV as isize,
1240 IDiv = LUA_OPIDIV as isize,
1241 BAnd = LUA_OPBAND as isize,
1242 BOr = LUA_OPBOR as isize,
1243 BXor = LUA_OPBXOR as isize,
1244 Shl = LUA_OPSHL as isize,
1245 Shr = LUA_OPSHR as isize,
1246 Unm = LUA_OPUNM as isize,
1247 BNot = LUA_OPBNOT as isize,
1248}
1249
1250#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1252pub enum Comparison {
1253 Eq = LUA_OPEQ as isize,
1254 Lt = LUA_OPLT as isize,
1255 Le = LUA_OPLE as isize,
1256}
1257
1258#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1260pub enum Type {
1261 None = LUA_TNONE as isize,
1262 Nil = LUA_TNIL as isize,
1263 Boolean = LUA_TBOOLEAN as isize,
1264 LightUserdata = LUA_TLIGHTUSERDATA as isize,
1265 Number = LUA_TNUMBER as isize,
1266 String = LUA_TSTRING as isize,
1267 Table = LUA_TTABLE as isize,
1268 Function = LUA_TFUNCTION as isize,
1269 Userdata = LUA_TUSERDATA as isize,
1270 Thread = LUA_TTHREAD as isize,
1271 Invalid,
1272}
1273
1274impl core::fmt::Display for Type {
1275 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1276 match self {
1277 Type::None => write!(f, "none"),
1278 Type::Nil => write!(f, "nil"),
1279 Type::Boolean => write!(f, "boolean"),
1280 Type::LightUserdata => write!(f, "lightuserdata"),
1281 Type::Number => write!(f, "number"),
1282 Type::String => write!(f, "string"),
1283 Type::Table => write!(f, "table"),
1284 Type::Function => write!(f, "function"),
1285 Type::Userdata => write!(f, "userdata"),
1286 Type::Thread => write!(f, "thread"),
1287 Type::Invalid => write!(f, "invalid"),
1288 }
1289 }
1290}
1291
1292impl Type {
1293 fn from_c_int(i: c_int) -> Type {
1294 match i {
1295 LUA_TNIL => Type::Nil,
1296 LUA_TBOOLEAN => Type::Boolean,
1297 LUA_TLIGHTUSERDATA => Type::LightUserdata,
1298 LUA_TNUMBER => Type::Number,
1299 LUA_TSTRING => Type::String,
1300 LUA_TTABLE => Type::Table,
1301 LUA_TFUNCTION => Type::Function,
1302 LUA_TUSERDATA => Type::Userdata,
1303 LUA_TTHREAD => Type::Thread,
1304 _ => Type::Invalid,
1305 }
1306 }
1307
1308 pub fn is_none_or_nil(&self) -> bool {
1309 matches!(*self, Type::None | Type::Nil)
1310 }
1311}
1312
1313#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1315pub enum GcOption {
1316 Stop = LUA_GCSTOP as isize,
1317 Restart = LUA_GCRESTART as isize,
1318 Collect = LUA_GCCOLLECT as isize,
1319 Count = LUA_GCCOUNT as isize,
1320 CountBytes = LUA_GCCOUNTB as isize,
1321 Step = LUA_GCSTEP as isize,
1322 SetPause = LUA_GCSETPAUSE as isize,
1323 SetStepMul = LUA_GCSETSTEPMUL as isize,
1324 IsRunning = LUA_GCISRUNNING as isize,
1325}
1326
1327#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1329pub enum GCMode {
1330 Incremental,
1331 Generational,
1332}
1333
1334#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1336pub enum ThreadStatus {
1337 Ok = LUA_OK as isize,
1338 Yield = LUA_YIELD as isize,
1339 RuntimeError = LUA_ERRRUN as isize,
1340 SyntaxError = LUA_ERRSYNTAX as isize,
1341 MemoryError = LUA_ERRMEM as isize,
1342 MessageHandlerError = LUA_ERRERR as isize,
1344 FileError = LUA_ERRFILE as isize,
1345}
1346
1347impl ThreadStatus {
1348 pub(crate) fn from_c_int(i: c_int) -> ThreadStatus {
1349 match i {
1350 LUA_OK => ThreadStatus::Ok,
1351 LUA_YIELD => ThreadStatus::Yield,
1352 LUA_ERRRUN => ThreadStatus::RuntimeError,
1353 LUA_ERRSYNTAX => ThreadStatus::SyntaxError,
1354 LUA_ERRMEM => ThreadStatus::MemoryError,
1355 LUA_ERRERR => ThreadStatus::MessageHandlerError,
1357 LUA_ERRFILE => ThreadStatus::FileError,
1358 _ => panic!("Unknown Lua error code: {}", i),
1359 }
1360 }
1361
1362 pub fn is_ok(self) -> bool {
1363 matches!(self, Self::Ok)
1364 }
1365
1366 pub fn is_err(self) -> bool {
1368 match self {
1369 ThreadStatus::RuntimeError
1370 | ThreadStatus::SyntaxError
1371 | ThreadStatus::MemoryError
1372 | ThreadStatus::MessageHandlerError
1374 | ThreadStatus::FileError => true,
1375 ThreadStatus::Ok | ThreadStatus::Yield => false,
1376 }
1377 }
1378}
1379
1380#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1382pub struct Reference(pub c_int);
1383
1384impl Default for Reference {
1385 fn default() -> Self {
1386 NOREF
1387 }
1388}
1389
1390pub const REFNIL: Reference = Reference(LUA_REFNIL);
1392
1393pub const NOREF: Reference = Reference(LUA_REFNIL);
1395
1396impl Reference {
1397 pub fn is_nil_ref(self) -> bool {
1399 self == REFNIL
1400 }
1401
1402 pub fn is_no_ref(self) -> bool {
1404 self == NOREF
1405 }
1406
1407 pub fn value(self) -> c_int {
1409 let Reference(value) = self;
1410 value
1411 }
1412}
1413
1414impl From<c_int> for Reference {
1415 fn from(i: c_int) -> Self {
1416 Self(i)
1417 }
1418}
1419
1420#[cfg(feature = "std")]
1421bitflags::bitflags! {
1422 pub struct HookMask: c_int {
1424 const MASKCALL = LUA_MASKCALL;
1426 const MASKRET = LUA_MASKRET;
1428 const MASKLINE = LUA_MASKLINE;
1430 const MASKCOUNT = LUA_MASKCOUNT;
1432 }
1433}
1434
1435impl lua_Debug {
1436 pub fn source(&self) -> Option<Cow<str>> {
1437 if self.source.is_null() {
1438 None
1439 } else {
1440 Some(unsafe { CStr::from_ptr(self.source).to_string_lossy() })
1441 }
1442 }
1443
1444 pub fn short_src(&self) -> Cow<str> {
1445 unsafe { CStr::from_ptr(self.short_src.as_ptr()).to_string_lossy() }
1446 }
1447
1448 pub fn name(&self) -> Option<Cow<str>> {
1449 if self.name.is_null() {
1450 None
1451 } else {
1452 Some(unsafe { CStr::from_ptr(self.name).to_string_lossy() })
1453 }
1454 }
1455
1456 pub fn what(&self) -> Option<Cow<str>> {
1457 if self.what.is_null() {
1458 None
1459 } else {
1460 Some(unsafe { CStr::from_ptr(self.what).to_string_lossy() })
1461 }
1462 }
1463
1464 pub fn namewhat(&self) -> Option<Cow<str>> {
1465 if self.namewhat.is_null() {
1466 None
1467 } else {
1468 Some(unsafe { CStr::from_ptr(self.namewhat).to_string_lossy() })
1469 }
1470 }
1471}