1use ffi;
24use ffi::{lua_State, lua_Debug};
25
26use libc::{c_int, c_void, c_char, size_t};
27use std::{mem, ptr, str, slice, any};
28use std::ffi::{CString, CStr};
29use std::ops::DerefMut;
30use std::sync::Mutex;
31use super::convert::{ToLua, FromLua};
32
33use ::{
34 Number,
35 Integer,
36 Function,
37 Allocator,
38 Hook,
39 Index,
40};
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub enum Arithmetic {
45 Add = ffi::LUA_OPADD as isize,
46 Sub = ffi::LUA_OPSUB as isize,
47 Mul = ffi::LUA_OPMUL as isize,
48 Mod = ffi::LUA_OPMOD as isize,
49 Pow = ffi::LUA_OPPOW as isize,
50 Div = ffi::LUA_OPDIV as isize,
51 IDiv = ffi::LUA_OPIDIV as isize,
52 BAnd = ffi::LUA_OPBAND as isize,
53 BOr = ffi::LUA_OPBOR as isize,
54 BXor = ffi::LUA_OPBXOR as isize,
55 Shl = ffi::LUA_OPSHL as isize,
56 Shr = ffi::LUA_OPSHR as isize,
57 Unm = ffi::LUA_OPUNM as isize,
58 BNot = ffi::LUA_OPBNOT as isize,
59}
60
61#[derive(Clone, Copy, Debug, PartialEq, Eq)]
63pub enum Comparison {
64 Eq = ffi::LUA_OPEQ as isize,
65 Lt = ffi::LUA_OPLT as isize,
66 Le = ffi::LUA_OPLE as isize,
67}
68
69#[must_use]
71#[derive(Clone, Copy, Debug, PartialEq, Eq)]
72pub enum ThreadStatus {
73 Ok = ffi::LUA_OK as isize,
74 Yield = ffi::LUA_YIELD as isize,
75 RuntimeError = ffi::LUA_ERRRUN as isize,
76 SyntaxError = ffi::LUA_ERRSYNTAX as isize,
77 MemoryError = ffi::LUA_ERRMEM as isize,
78 GcError = ffi::LUA_ERRGCMM as isize,
79 MessageHandlerError = ffi::LUA_ERRERR as isize,
80 FileError = ffi::LUA_ERRFILE as isize,
81}
82
83impl ThreadStatus {
84 fn from_c_int(i: c_int) -> ThreadStatus {
85 match i {
86 ffi::LUA_OK => ThreadStatus::Ok,
87 ffi::LUA_YIELD => ThreadStatus::Yield,
88 ffi::LUA_ERRRUN => ThreadStatus::RuntimeError,
89 ffi::LUA_ERRSYNTAX => ThreadStatus::SyntaxError,
90 ffi::LUA_ERRMEM => ThreadStatus::MemoryError,
91 ffi::LUA_ERRGCMM => ThreadStatus::GcError,
92 ffi::LUA_ERRERR => ThreadStatus::MessageHandlerError,
93 ffi::LUA_ERRFILE => ThreadStatus::FileError,
94 _ => panic!("Unknown Lua error code: {}", i),
95 }
96 }
97
98 pub fn is_err(self) -> bool {
100 match self {
101 ThreadStatus::RuntimeError |
102 ThreadStatus::SyntaxError |
103 ThreadStatus::MemoryError |
104 ThreadStatus::GcError |
105 ThreadStatus::MessageHandlerError |
106 ThreadStatus::FileError => true,
107 ThreadStatus::Ok |
108 ThreadStatus::Yield => false,
109 }
110 }
111}
112
113#[derive(Clone, Copy, Debug, PartialEq, Eq)]
115pub enum GcOption {
116 Stop = ffi::LUA_GCSTOP as isize,
117 Restart = ffi::LUA_GCRESTART as isize,
118 Collect = ffi::LUA_GCCOLLECT as isize,
119 Count = ffi::LUA_GCCOUNT as isize,
120 CountBytes = ffi::LUA_GCCOUNTB as isize,
121 Step = ffi::LUA_GCSTEP as isize,
122 SetPause = ffi::LUA_GCSETPAUSE as isize,
123 SetStepMul = ffi::LUA_GCSETSTEPMUL as isize,
124 IsRunning = ffi::LUA_GCISRUNNING as isize,
125}
126
127#[derive(Clone, Copy, Debug, PartialEq, Eq)]
129pub enum Type {
130 None = ffi::LUA_TNONE as isize,
131 Nil = ffi::LUA_TNIL as isize,
132 Boolean = ffi::LUA_TBOOLEAN as isize,
133 LightUserdata = ffi::LUA_TLIGHTUSERDATA as isize,
134 Number = ffi::LUA_TNUMBER as isize,
135 String = ffi::LUA_TSTRING as isize,
136 Table = ffi::LUA_TTABLE as isize,
137 Function = ffi::LUA_TFUNCTION as isize,
138 Userdata = ffi::LUA_TUSERDATA as isize,
139 Thread = ffi::LUA_TTHREAD as isize,
140}
141
142impl Type {
143 fn from_c_int(i: c_int) -> Option<Type> {
144 match i {
145 ffi::LUA_TNIL => Some(Type::Nil),
146 ffi::LUA_TBOOLEAN => Some(Type::Boolean),
147 ffi::LUA_TLIGHTUSERDATA => Some(Type::LightUserdata),
148 ffi::LUA_TNUMBER => Some(Type::Number),
149 ffi::LUA_TSTRING => Some(Type::String),
150 ffi::LUA_TTABLE => Some(Type::Table),
151 ffi::LUA_TFUNCTION => Some(Type::Function),
152 ffi::LUA_TUSERDATA => Some(Type::Userdata),
153 ffi::LUA_TTHREAD => Some(Type::Thread),
154 _ => None
155 }
156 }
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub enum Library {
162 Base,
163 Coroutine,
164 Table,
165 Io,
166 Os,
167 String,
168 Utf8,
169 Bit32,
170 Math,
171 Debug,
172 Package,
173}
174
175impl Library {
176 pub fn name(&self) -> &'static str {
178 use self::Library::*;
179 match *self {
180 Base => "_G",
181 Coroutine => "coroutine",
182 Table => "table",
183 Io => "io",
184 Os => "os",
185 String => "string",
186 Utf8 => "utf8",
187 Bit32 => "bit32",
188 Math => "math",
189 Debug => "debug",
190 Package => "package",
191 }
192 }
193 #[allow(non_snake_case)]
195 pub fn loader(&self) -> unsafe extern fn (L: *mut lua_State) -> c_int {
196 use self::Library::*;
197 match *self {
198 Base => ffi::luaopen_base,
199 Coroutine => ffi::luaopen_coroutine,
200 Table => ffi::luaopen_table,
201 Io => ffi::luaopen_io,
202 Os => ffi::luaopen_os,
203 String => ffi::luaopen_string,
204 Utf8 => ffi::luaopen_utf8,
205 Bit32 => ffi::luaopen_bit32,
206 Math => ffi::luaopen_math,
207 Debug => ffi::luaopen_debug,
208 Package => ffi::luaopen_package,
209 }
210 }
211}
212
213#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
215pub struct Reference(c_int);
216
217pub const REFNIL: Reference = Reference(ffi::LUA_REFNIL);
219
220pub const NOREF: Reference = Reference(ffi::LUA_REFNIL);
222
223impl Reference {
224 pub fn is_nil_ref(self) -> bool {
226 self == REFNIL
227 }
228
229 pub fn is_no_ref(self) -> bool {
231 self == NOREF
232 }
233
234 pub fn value(self) -> c_int {
236 let Reference(value) = self;
237 value
238 }
239}
240
241bitflags! {
242 #[doc="Hook point masks for `lua_sethook`."]
243 flags HookMask: c_int {
244 #[doc="Called when the interpreter calls a function."]
245 const MASKCALL = ffi::LUA_MASKCALL,
246 #[doc="Called when the interpreter returns from a function."]
247 const MASKRET = ffi::LUA_MASKRET,
248 #[doc="Called when the interpreter is about to start the execution of a new line of code."]
249 const MASKLINE = ffi::LUA_MASKLINE,
250 #[doc="Called after the interpreter executes every `count` instructions."]
251 const MASKCOUNT = ffi::LUA_MASKCOUNT
252 }
253}
254
255pub const MULTRET: c_int = ffi::LUA_MULTRET;
258
259pub const REGISTRYINDEX: Index = ffi::LUA_REGISTRYINDEX;
261
262pub const RIDX_MAINTHREAD: Integer = ffi::LUA_RIDX_MAINTHREAD;
264pub const RIDX_GLOBALS: Integer = ffi::LUA_RIDX_GLOBALS;
266
267unsafe extern fn continue_func<F>(st: *mut lua_State, status: c_int, ctx: ffi::lua_KContext) -> c_int
268 where F: FnOnce(&mut State, ThreadStatus) -> c_int
269{
270 mem::transmute::<_, Box<F>>(ctx)(&mut State::from_ptr(st), ThreadStatus::from_c_int(status))
271}
272
273pub type Extra = Box<any::Any + 'static + Send>;
275type ExtraHolder = *mut *mut Mutex<Option<Extra>>;
276
277unsafe extern fn alloc_func(_: *mut c_void, ptr: *mut c_void, old_size: size_t, new_size: size_t) -> *mut c_void {
278 #[inline]
285 fn divide_size(size: size_t) -> usize {
286 1 + (size - 1) / mem::size_of::<usize>()
287 }
288
289 let ptr = ptr as *mut usize;
290 if new_size == 0 {
291 if !ptr.is_null() {
293 drop(Vec::<usize>::from_raw_parts(ptr, 0, divide_size(old_size)));
295 }
296 ptr::null_mut()
297 } else {
298 let mut vec;
300 if ptr.is_null() {
301 vec = Vec::<usize>::with_capacity(divide_size(new_size));
303 } else {
304 if new_size > old_size {
306 vec = Vec::<usize>::from_raw_parts(ptr, 0, divide_size(old_size));
308 vec.reserve_exact(divide_size(new_size));
309 } else {
310 vec = Vec::<usize>::from_raw_parts(ptr, divide_size(new_size), divide_size(old_size));
312 vec.shrink_to_fit();
313 }
314 }
315 let res = vec.as_mut_ptr();
316 mem::forget(vec); res as *mut c_void
318 }
319}
320
321#[allow(non_snake_case)]
334pub struct State {
335 L: *mut lua_State,
336 owned: bool
337}
338
339unsafe impl Send for State {}
340
341impl State {
342 pub fn new() -> State {
345 unsafe {
346 let state = ffi::lua_newstate(Some(alloc_func), ptr::null_mut());
347 let extra_ptr = ffi::lua_getextraspace(state) as ExtraHolder;
348 let mutex = Box::new(Mutex::new(None));
349 *extra_ptr = Box::into_raw(mutex);
350 State { L: state, owned: true }
351 }
352 }
353
354 #[allow(non_snake_case)]
357 pub unsafe fn from_ptr(L: *mut lua_State) -> State {
358 State { L: L, owned: false }
359 }
360
361 pub fn as_ptr(&self) -> *mut lua_State {
363 self.L
364 }
365
366 pub fn open_libs(&mut self) {
368 unsafe { ffi::luaL_openlibs(self.L) }
369 }
370
371 pub fn preload_library(&mut self, lib: Library) {
373 unsafe {
374 let pre = CString::new("_PRELOAD").unwrap();
375 ffi::luaL_getsubtable(self.L, ffi::LUA_REGISTRYINDEX, pre.as_ptr());
376 self.push_fn(Some(lib.loader()));
377 self.set_field(-2, lib.name());
378 self.pop(1); }
380 }
381
382 pub fn load_library(&mut self, lib: Library) {
384 self.requiref(lib.name(), Some(lib.loader()), true);
385 self.pop(1); }
387
388 pub fn open_base(&mut self) -> c_int {
390 unsafe { ffi::luaopen_base(self.L) }
391 }
392
393 pub fn open_coroutine(&mut self) -> c_int {
395 unsafe { ffi::luaopen_coroutine(self.L) }
396 }
397
398 pub fn open_table(&mut self) -> c_int {
400 unsafe { ffi::luaopen_table(self.L) }
401 }
402
403 pub fn open_io(&mut self) -> c_int {
405 unsafe { ffi::luaopen_io(self.L) }
406 }
407
408 pub fn open_os(&mut self) -> c_int {
410 unsafe { ffi::luaopen_os(self.L) }
411 }
412
413 pub fn open_string(&mut self) -> c_int {
415 unsafe { ffi::luaopen_string(self.L) }
416 }
417
418 pub fn open_utf8(&mut self) -> c_int {
420 unsafe { ffi::luaopen_utf8(self.L) }
421 }
422
423 pub fn open_bit32(&mut self) -> c_int {
425 unsafe { ffi::luaopen_bit32(self.L) }
426 }
427
428 pub fn open_math(&mut self) -> c_int {
430 unsafe { ffi::luaopen_math(self.L) }
431 }
432
433 pub fn open_debug(&mut self) -> c_int {
435 unsafe { ffi::luaopen_debug(self.L) }
436 }
437
438 pub fn open_package(&mut self) -> c_int {
440 unsafe { ffi::luaopen_package(self.L) }
441 }
442
443 pub fn do_file(&mut self, filename: &str) -> ThreadStatus {
445 let c_str = CString::new(filename).unwrap();
446 let result = unsafe {
447 ffi::luaL_dofile(self.L, c_str.as_ptr())
448 };
449 ThreadStatus::from_c_int(result)
450 }
451
452 pub fn do_string(&mut self, s: &str) -> ThreadStatus {
454 let c_str = CString::new(s).unwrap();
455 let result = unsafe {
456 ffi::luaL_dostring(self.L, c_str.as_ptr())
457 };
458 ThreadStatus::from_c_int(result)
459 }
460
461 pub fn push<T: ToLua>(&mut self, value: T) {
463 value.to_lua(self);
464 }
465
466 pub fn to_type<T: FromLua>(&mut self, index: Index) -> Option<T> {
469 FromLua::from_lua(self, index)
470 }
471
472 pub fn close(self) {
477 if !self.owned {
479 panic!("cannot explicitly close non-owned Lua state")
480 }
481 }
482
483 pub fn new_thread(&mut self) -> State {
485 unsafe {
486 State::from_ptr(ffi::lua_newthread(self.L))
487 }
488 }
489
490 pub fn at_panic(&mut self, panicf: Function) -> Function {
492 unsafe { ffi::lua_atpanic(self.L, panicf) }
493 }
494
495 pub fn version(state: Option<&mut State>) -> Number {
497 let ptr = match state {
498 Some(state) => state.L,
499 None => ptr::null_mut()
500 };
501 unsafe { *ffi::lua_version(ptr) }
502 }
503
504 pub fn abs_index(&mut self, idx: Index) -> Index {
509 unsafe { ffi::lua_absindex(self.L, idx) }
510 }
511
512 pub fn get_top(&mut self) -> Index {
514 unsafe { ffi::lua_gettop(self.L) }
515 }
516
517 pub fn set_top(&mut self, index: Index) {
519 unsafe { ffi::lua_settop(self.L, index) }
520 }
521
522 pub fn push_value(&mut self, index: Index) {
524 unsafe { ffi::lua_pushvalue(self.L, index) }
525 }
526
527 pub fn rotate(&mut self, idx: Index, n: c_int) {
529 unsafe { ffi::lua_rotate(self.L, idx, n) }
530 }
531
532 pub fn copy(&mut self, from_idx: Index, to_idx: Index) {
534 unsafe { ffi::lua_copy(self.L, from_idx, to_idx) }
535 }
536
537 pub fn check_stack(&mut self, extra: c_int) -> bool {
539 let result = unsafe { ffi::lua_checkstack(self.L, extra) };
540 result != 0
541 }
542
543 pub fn xmove(&mut self, to: &mut State, n: c_int) {
545 unsafe { ffi::lua_xmove(self.L, to.L, n) }
546 }
547
548 pub fn is_number(&mut self, index: Index) -> bool {
553 unsafe { ffi::lua_isnumber(self.L, index) == 1 }
554 }
555
556 pub fn is_string(&mut self, index: Index) -> bool {
558 unsafe { ffi::lua_isstring(self.L, index) == 1 }
559 }
560
561 pub fn is_native_fn(&mut self, index: Index) -> bool {
563 unsafe { ffi::lua_iscfunction(self.L, index) == 1 }
564 }
565
566 pub fn is_integer(&mut self, index: Index) -> bool {
568 unsafe { ffi::lua_isinteger(self.L, index) == 1 }
569 }
570
571 pub fn is_userdata(&mut self, index: Index) -> bool {
573 unsafe { ffi::lua_isuserdata(self.L, index) == 1 }
574 }
575
576 pub fn type_of(&mut self, index: Index) -> Option<Type> {
578 let result = unsafe { ffi::lua_type(self.L, index) };
579 Type::from_c_int(result)
580 }
581
582 pub fn typename_of(&mut self, tp: Type) -> &'static str {
584 unsafe {
585 let ptr = ffi::lua_typename(self.L, tp as c_int);
586 let slice = CStr::from_ptr(ptr).to_bytes();
587 str::from_utf8(slice).unwrap()
588 }
589 }
590
591 pub fn to_numberx(&mut self, index: Index) -> Option<Number> {
593 let mut isnum: c_int = 0;
594 let result = unsafe { ffi::lua_tonumberx(self.L, index, &mut isnum) };
595 if isnum == 0 {
596 None
597 } else {
598 Some(result)
599 }
600 }
601
602 pub fn to_integerx(&mut self, index: Index) -> Option<Integer> {
604 let mut isnum: c_int = 0;
605 let result = unsafe { ffi::lua_tointegerx(self.L, index, &mut isnum) };
606 if isnum == 0 {
607 None
608 } else {
609 Some(result)
610 }
611 }
612
613 pub fn to_bool(&mut self, index: Index) -> bool {
615 let result = unsafe { ffi::lua_toboolean(self.L, index) };
616 result != 0
617 }
618
619 pub fn raw_len(&mut self, index: Index) -> size_t {
623 unsafe { ffi::lua_rawlen(self.L, index) }
624 }
625
626 pub fn to_native_fn(&mut self, index: Index) -> Function {
628 let result = unsafe { ffi::lua_tocfunction(self.L, index) };
629 result
630 }
631
632 pub fn to_userdata(&mut self, index: Index) -> *mut c_void {
634 unsafe { ffi::lua_touserdata(self.L, index) }
635 }
636
637 pub unsafe fn to_userdata_typed<'a, T>(&'a mut self, index: Index) -> Option<&'a mut T> {
640 mem::transmute(self.to_userdata(index))
641 }
642
643 pub fn to_thread(&mut self, index: Index) -> Option<State> {
645 let state = unsafe { ffi::lua_tothread(self.L, index) };
646 if state.is_null() {
647 None
648 } else {
649 Some(unsafe { State::from_ptr(state) })
650 }
651 }
652
653 pub fn to_pointer(&mut self, index: Index) -> *const c_void {
655 unsafe { ffi::lua_topointer(self.L, index) }
656 }
657
658 pub fn arith(&mut self, op: Arithmetic) {
663 unsafe { ffi::lua_arith(self.L, op as c_int) }
664 }
665
666 pub fn raw_equal(&mut self, idx1: Index, idx2: Index) -> bool {
668 let result = unsafe { ffi::lua_rawequal(self.L, idx1, idx2) };
669 result != 0
670 }
671
672 pub fn compare(&mut self, idx1: Index, idx2: Index, op: Comparison) -> bool {
674 let result = unsafe { ffi::lua_compare(self.L, idx1, idx2, op as c_int) };
675 result != 0
676 }
677
678 pub fn push_nil(&mut self) {
683 unsafe { ffi::lua_pushnil(self.L) }
684 }
685
686 pub fn push_number(&mut self, n: Number) {
688 unsafe { ffi::lua_pushnumber(self.L, n) }
689 }
690
691 pub fn push_integer(&mut self, i: Integer) {
693 unsafe { ffi::lua_pushinteger(self.L, i) }
694 }
695
696 pub fn push_string(&mut self, s: &str) {
700 unsafe { ffi::lua_pushlstring(self.L, s.as_ptr() as *const _, s.len() as size_t) };
701 }
702
703 pub fn push_closure(&mut self, f: Function, n: c_int) {
708 unsafe { ffi::lua_pushcclosure(self.L, f, n) }
709 }
710
711 pub fn push_bool(&mut self, b: bool) {
713 unsafe { ffi::lua_pushboolean(self.L, b as c_int) }
714 }
715
716 pub unsafe fn push_light_userdata<T>(&mut self, ud: *mut T) {
721 ffi::lua_pushlightuserdata(self.L, mem::transmute(ud))
722 }
723
724 pub fn push_thread(&mut self) -> bool {
726 let result = unsafe { ffi::lua_pushthread(self.L) };
727 result != 1
728 }
729
730 pub fn get_global(&mut self, name: &str) -> Type {
735 let c_str = CString::new(name).unwrap();
736 let ty = unsafe {
737 ffi::lua_getglobal(self.L, c_str.as_ptr())
738 };
739 Type::from_c_int(ty).unwrap()
740 }
741
742 pub fn get_table(&mut self, index: Index) -> Type {
744 let ty = unsafe { ffi::lua_gettable(self.L, index) };
745 Type::from_c_int(ty).unwrap()
746 }
747
748 pub fn get_field(&mut self, index: Index, k: &str) -> Type {
750 let c_str = CString::new(k).unwrap();
751 let ty = unsafe {
752 ffi::lua_getfield(self.L, index, c_str.as_ptr())
753 };
754 Type::from_c_int(ty).unwrap()
755 }
756
757 pub fn geti(&mut self, index: Index, i: Integer) -> Type {
759 let ty = unsafe {
760 ffi::lua_geti(self.L, index, i)
761 };
762 Type::from_c_int(ty).unwrap()
763 }
764
765 pub fn raw_get(&mut self, index: Index) -> Type {
767 let ty = unsafe { ffi::lua_rawget(self.L, index) };
768 Type::from_c_int(ty).unwrap()
769 }
770
771 pub fn raw_geti(&mut self, index: Index, n: Integer) -> Type {
773 let ty = unsafe { ffi::lua_rawgeti(self.L, index, n) };
774 Type::from_c_int(ty).unwrap()
775 }
776
777 pub fn raw_getp<T>(&mut self, index: Index, p: *const T) -> Type {
779 let ty = unsafe { ffi::lua_rawgetp(self.L, index, mem::transmute(p)) };
780 Type::from_c_int(ty).unwrap()
781 }
782
783 pub fn create_table(&mut self, narr: c_int, nrec: c_int) {
785 unsafe { ffi::lua_createtable(self.L, narr, nrec) }
786 }
787
788 pub fn new_userdata(&mut self, sz: size_t) -> *mut c_void {
792 unsafe { ffi::lua_newuserdata(self.L, sz) }
793 }
794
795 pub fn new_userdata_typed<T>(&mut self) -> *mut T {
806 self.new_userdata(mem::size_of::<T>() as size_t) as *mut T
807 }
808
809 pub fn get_metatable(&mut self, objindex: Index) -> bool {
811 let result = unsafe { ffi::lua_getmetatable(self.L, objindex) };
812 result != 0
813 }
814
815 pub fn get_uservalue(&mut self, idx: Index) -> Type {
817 let result = unsafe { ffi::lua_getuservalue(self.L, idx) };
818 Type::from_c_int(result).unwrap()
819 }
820
821 pub fn set_global(&mut self, var: &str) {
826 let c_str = CString::new(var).unwrap();
827 unsafe { ffi::lua_setglobal(self.L, c_str.as_ptr()) }
828 }
829
830 pub fn set_table(&mut self, idx: Index) {
832 unsafe { ffi::lua_settable(self.L, idx) }
833 }
834
835 pub fn set_field(&mut self, idx: Index, k: &str) {
837 let c_str = CString::new(k).unwrap();
838 unsafe { ffi::lua_setfield(self.L, idx, c_str.as_ptr()) }
839 }
840
841 pub fn seti(&mut self, idx: Index, n: Integer) {
843 unsafe { ffi::lua_seti(self.L, idx, n) }
844 }
845
846 pub fn raw_set(&mut self, idx: Index) {
848 unsafe { ffi::lua_rawset(self.L, idx) }
849 }
850
851 pub fn raw_seti(&mut self, idx: Index, n: Integer) {
853 unsafe { ffi::lua_rawseti(self.L, idx, n) }
854 }
855
856 pub fn raw_setp<T>(&mut self, idx: Index, p: *const T) {
858 unsafe { ffi::lua_rawsetp(self.L, idx, mem::transmute(p)) }
859 }
860
861 pub fn set_metatable(&mut self, objindex: Index) {
863 unsafe { ffi::lua_setmetatable(self.L, objindex) };
864 }
865
866 pub fn set_uservalue(&mut self, idx: Index) {
868 unsafe { ffi::lua_setuservalue(self.L, idx) }
869 }
870
871 pub fn callk<F>(&mut self, nargs: c_int, nresults: c_int, continuation: F)
876 where F: FnOnce(&mut State, ThreadStatus) -> c_int
877 {
878 let func = continue_func::<F>;
879 unsafe {
880 let ctx = mem::transmute(Box::new(continuation));
881 ffi::lua_callk(self.L, nargs, nresults, ctx, Some(func));
882 func(self.L, ffi::LUA_OK, ctx);
884 }
885 }
886
887 pub fn call(&mut self, nargs: c_int, nresults: c_int) {
889 unsafe { ffi::lua_call(self.L, nargs, nresults) }
890 }
891
892 pub fn pcallk<F>(&mut self, nargs: c_int, nresults: c_int, msgh: c_int, continuation: F) -> c_int
894 where F: FnOnce(&mut State, ThreadStatus) -> c_int
895 {
896 let func = continue_func::<F>;
897 unsafe {
898 let ctx = mem::transmute(Box::new(continuation));
899 func(self.L, ffi::lua_pcallk(self.L, nargs, nresults, msgh, ctx, Some(func)), ctx)
901 }
902 }
903
904 pub fn pcall(&mut self, nargs: c_int, nresults: c_int, msgh: c_int) -> ThreadStatus {
906 let result = unsafe {
907 ffi::lua_pcall(self.L, nargs, nresults, msgh)
908 };
909 ThreadStatus::from_c_int(result)
910 }
911
912 pub fn load<F>(&mut self, mut reader: F, source: &str, mode: &str) -> ThreadStatus
915 where F: FnMut(&mut State) -> &[u8]
916 {
917 unsafe extern fn read<F>(st: *mut lua_State, ud: *mut c_void, sz: *mut size_t) -> *const c_char
918 where F: FnMut(&mut State) -> &[u8]
919 {
920 let mut state = State::from_ptr(st);
921 let slice = mem::transmute::<_, &mut F>(ud)(&mut state);
922 *sz = slice.len() as size_t;
923 slice.as_ptr() as *const _
924 }
925 let source_c_str = CString::new(source).unwrap();
926 let mode_c_str = CString::new(mode).unwrap();
927 let result = unsafe {
928 ffi::lua_load(self.L, Some(read::<F>), mem::transmute(&mut reader), source_c_str.as_ptr(), mode_c_str.as_ptr())
929 };
930 ThreadStatus::from_c_int(result)
931 }
932
933 pub fn dump<F>(&mut self, mut writer: F, strip: bool) -> c_int
937 where F: FnMut(&mut State, &[u8]) -> c_int
938 {
939 unsafe extern fn write<F>(st: *mut lua_State, p: *const c_void, sz: size_t, ud: *mut c_void) -> c_int
940 where F: FnMut(&mut State, &[u8]) -> c_int
941 {
942 mem::transmute::<_, &mut F>(ud)(&mut State::from_ptr(st), slice::from_raw_parts(p as *const _, sz as usize))
943 }
944 unsafe { ffi::lua_dump(self.L, Some(write::<F>), mem::transmute(&mut writer), strip as c_int) }
945 }
946
947 pub fn co_yieldk<F>(&mut self, nresults: c_int, continuation: F) -> !
952 where F: FnOnce(&mut State, ThreadStatus) -> c_int
953 {
954 unsafe { ffi::lua_yieldk(self.L, nresults, mem::transmute(Box::new(continuation)), Some(continue_func::<F>)) };
955 panic!("co_yieldk called in non-coroutine context; check is_yieldable first")
956 }
957
958 pub fn co_yield(&mut self, nresults: c_int) -> ! {
961 unsafe { ffi::lua_yield(self.L, nresults) };
962 panic!("co_yield called in non-coroutine context; check is_yieldable first")
963 }
964
965 pub fn resume(&mut self, from: Option<&mut State>, nargs: c_int) -> ThreadStatus {
967 let from_ptr = match from {
968 Some(state) => state.L,
969 None => ptr::null_mut()
970 };
971 let result = unsafe {
972 ffi::lua_resume(self.L, from_ptr, nargs)
973 };
974 ThreadStatus::from_c_int(result)
975 }
976
977 pub fn status(&mut self) -> ThreadStatus {
979 let result = unsafe { ffi::lua_status(self.L) };
980 ThreadStatus::from_c_int(result)
981 }
982
983 pub fn is_yieldable(&mut self) -> bool {
985 let result = unsafe { ffi::lua_isyieldable(self.L) };
986 result != 0
987 }
988
989 pub fn gc(&mut self, what: GcOption, data: c_int) -> c_int {
995 unsafe { ffi::lua_gc(self.L, what as c_int, data) }
996 }
997
998 pub fn error(&mut self) -> ! {
1003 unsafe { ffi::lua_error(self.L) };
1004 unreachable!()
1005 }
1006
1007 pub fn next(&mut self, idx: Index) -> bool {
1009 let result = unsafe { ffi::lua_next(self.L, idx) };
1010 result != 0
1011 }
1012
1013 pub fn concat(&mut self, n: c_int) {
1015 unsafe { ffi::lua_concat(self.L, n) }
1016 }
1017
1018 pub fn len(&mut self, idx: Index) {
1020 unsafe { ffi::lua_len(self.L, idx) }
1021 }
1022
1023 pub fn string_to_number(&mut self, s: &str) -> size_t {
1025 let c_str = CString::new(s).unwrap();
1026 unsafe { ffi::lua_stringtonumber(self.L, c_str.as_ptr()) }
1027 }
1028
1029 pub fn get_alloc_fn(&mut self) -> (Allocator, *mut c_void) {
1031 let mut slot = ptr::null_mut();
1032 (unsafe { ffi::lua_getallocf(self.L, &mut slot) }, slot)
1033 }
1034
1035 pub fn set_alloc_fn(&mut self, f: Allocator, ud: *mut c_void) {
1037 unsafe { ffi::lua_setallocf(self.L, f, ud) }
1038 }
1039
1040 pub fn set_extra(&mut self, extra: Option<Extra>) -> Option<Extra> {
1046 self.with_extra(|opt_extra| mem::replace(opt_extra, extra))
1047 }
1048
1049 pub fn with_extra<F, R>(&mut self, closure: F) -> R
1051 where F: FnOnce(&mut Option<Extra>) -> R {
1052 unsafe {
1053 let extra_ptr = ffi::lua_getextraspace(self.L) as ExtraHolder;
1054 let mutex = Box::from_raw(*extra_ptr);
1055 let result = {
1056 let mut guard = mutex.lock().unwrap();
1057 closure(guard.deref_mut())
1058 };
1059 mem::forget(mutex);
1060 result
1061 }
1062 }
1063
1064 pub fn with_extra_typed<T, F, R>(&mut self, closure: F) -> R
1071 where T: any::Any, F: FnOnce(&mut T) -> R {
1072 self.with_extra(|extra| {
1073 let data = extra.as_mut().unwrap()
1074 .downcast_mut::<T>().unwrap();
1075 closure(data)
1076 })
1077 }
1078
1079 pub fn to_number(&mut self, index: Index) -> Number {
1081 unsafe { ffi::lua_tonumber(self.L, index) }
1082 }
1083
1084 pub fn to_integer(&mut self, index: Index) -> Integer {
1086 unsafe { ffi::lua_tointeger(self.L, index) }
1087 }
1088
1089 pub fn pop(&mut self, n: c_int) {
1091 unsafe { ffi::lua_pop(self.L, n) }
1092 }
1093
1094 pub fn new_table(&mut self) {
1096 unsafe { ffi::lua_newtable(self.L) }
1097 }
1098
1099 pub fn register(&mut self, n: &str, f: Function) {
1101 let c_str = CString::new(n).unwrap();
1102 unsafe { ffi::lua_register(self.L, c_str.as_ptr(), f) }
1103 }
1104
1105 pub fn push_fn(&mut self, f: Function) {
1107 unsafe { ffi::lua_pushcfunction(self.L, f) }
1108 }
1109
1110 pub fn is_fn(&mut self, index: Index) -> bool {
1112 unsafe { ffi::lua_isfunction(self.L, index) == 1 }
1113 }
1114
1115 pub fn is_table(&mut self, index: Index) -> bool {
1117 unsafe { ffi::lua_istable(self.L, index) == 1 }
1118 }
1119
1120 pub fn is_light_userdata(&mut self, index: Index) -> bool {
1122 unsafe { ffi::lua_islightuserdata(self.L, index) == 1 }
1123 }
1124
1125 pub fn is_nil(&mut self, index: Index) -> bool {
1127 unsafe { ffi::lua_isnil(self.L, index) == 1 }
1128 }
1129
1130 pub fn is_bool(&mut self, index: Index) -> bool {
1132 unsafe { ffi::lua_isboolean(self.L, index) == 1 }
1133 }
1134
1135 pub fn is_thread(&mut self, index: Index) -> bool {
1137 unsafe { ffi::lua_isthread(self.L, index) == 1 }
1138 }
1139
1140 pub fn is_none(&mut self, index: Index) -> bool {
1142 unsafe { ffi::lua_isnone(self.L, index) == 1 }
1143 }
1144
1145 pub fn is_none_or_nil(&mut self, index: Index) -> bool {
1147 unsafe { ffi::lua_isnoneornil(self.L, index) == 1 }
1148 }
1149
1150 pub fn push_global_table(&mut self) {
1154 unsafe { ffi::lua_pushglobaltable(self.L) };
1155 }
1156
1157 pub fn insert(&mut self, idx: Index) {
1159 unsafe { ffi::lua_insert(self.L, idx) }
1160 }
1161
1162 pub fn remove(&mut self, idx: Index) {
1164 unsafe { ffi::lua_remove(self.L, idx) }
1165 }
1166
1167 pub fn replace(&mut self, idx: Index) {
1169 unsafe { ffi::lua_replace(self.L, idx) }
1170 }
1171
1172 pub fn get_stack(&mut self, level: c_int) -> Option<lua_Debug> {
1177 let mut ar: lua_Debug = unsafe { mem::uninitialized() };
1178 let result = unsafe { ffi::lua_getstack(self.L, level, &mut ar) };
1179 if result == 0 {
1180 None
1181 } else {
1182 Some(ar)
1183 }
1184 }
1185
1186 pub fn get_info(&mut self, what: &str) -> Option<lua_Debug> {
1188 let mut ar: lua_Debug = unsafe { mem::uninitialized() };
1189 let c_str = CString::new(what).unwrap();
1190 let result = unsafe { ffi::lua_getinfo(self.L, c_str.as_ptr(), &mut ar) };
1191 if result == 0 {
1192 None
1193 } else {
1194 Some(ar)
1195 }
1196 }
1197
1198 pub fn get_local(&mut self, ar: &lua_Debug, n: c_int) -> Option<&str> {
1200 let ptr = unsafe { ffi::lua_getlocal(self.L, ar, n) };
1201 if ptr.is_null() {
1202 None
1203 } else {
1204 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
1205 str::from_utf8(slice).ok()
1206 }
1207 }
1208
1209 pub fn set_local(&mut self, ar: &lua_Debug, n: c_int) -> Option<&str> {
1211 let ptr = unsafe { ffi::lua_setlocal(self.L, ar, n) };
1212 if ptr.is_null() {
1213 None
1214 } else {
1215 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
1216 str::from_utf8(slice).ok()
1217 }
1218 }
1219
1220 pub fn get_upvalue(&mut self, funcindex: Index, n: c_int) -> Option<&str> {
1222 let ptr = unsafe { ffi::lua_getupvalue(self.L, funcindex, n) };
1223 if ptr.is_null() {
1224 None
1225 } else {
1226 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
1227 str::from_utf8(slice).ok()
1228 }
1229 }
1230
1231 pub fn set_upvalue(&mut self, funcindex: Index, n: c_int) -> Option<&str> {
1233 let ptr = unsafe { ffi::lua_setupvalue(self.L, funcindex, n) };
1234 if ptr.is_null() {
1235 None
1236 } else {
1237 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
1238 str::from_utf8(slice).ok()
1239 }
1240 }
1241
1242 pub fn upvalue_id(&mut self, funcindex: Index, n: c_int) -> *mut c_void {
1244 unsafe { ffi::lua_upvalueid(self.L, funcindex, n) }
1245 }
1246
1247 pub fn upvalue_join(&mut self, fidx1: Index, n1: c_int, fidx2: Index, n2: c_int) {
1249 unsafe { ffi::lua_upvaluejoin(self.L, fidx1, n1, fidx2, n2) }
1250 }
1251
1252 pub fn set_hook(&mut self, func: Hook, mask: HookMask, count: c_int) {
1254 unsafe { ffi::lua_sethook(self.L, func, mask.bits(), count) }
1255 }
1256
1257 pub fn get_hook(&mut self) -> Hook {
1259 unsafe { ffi::lua_gethook(self.L) }
1260 }
1261
1262 pub fn get_hook_mask(&mut self) -> HookMask {
1264 let result = unsafe { ffi::lua_gethookmask(self.L) };
1265 HookMask::from_bits_truncate(result)
1266 }
1267
1268 pub fn get_hook_count(&mut self) -> c_int {
1270 unsafe { ffi::lua_gethookcount(self.L) }
1271 }
1272
1273 pub fn check_version(&mut self) {
1278 unsafe { ffi::luaL_checkversion(self.L) }
1279 }
1280
1281 pub fn get_metafield(&mut self, obj: Index, e: &str) -> bool {
1283 let c_str = CString::new(e).unwrap();
1284 let result = unsafe {
1285 ffi::luaL_getmetafield(self.L, obj, c_str.as_ptr())
1286 };
1287 result != 0
1288 }
1289
1290 pub fn call_meta(&mut self, obj: Index, e: &str) -> bool {
1292 let c_str = CString::new(e).unwrap();
1293 let result = unsafe {
1294 ffi::luaL_callmeta(self.L, obj, c_str.as_ptr())
1295 };
1296 result != 0
1297 }
1298
1299 pub fn to_str(&mut self, index: Index) -> Option<&str> {
1304 let mut len = 0;
1305 let ptr = unsafe { ffi::luaL_tolstring(self.L, index, &mut len) };
1306 if ptr.is_null() {
1307 None
1308 } else {
1309 let slice = unsafe { slice::from_raw_parts(ptr as *const u8, len as usize) };
1310 str::from_utf8(slice).ok()
1311 }
1312 }
1313
1314 pub fn to_str_in_place(&mut self, index: Index) -> Option<&str> {
1319 let mut len = 0;
1320 let ptr = unsafe { ffi::lua_tolstring(self.L, index, &mut len) };
1321 if ptr.is_null() {
1322 None
1323 } else {
1324 let slice = unsafe { slice::from_raw_parts(ptr as *const u8, len as usize) };
1325 str::from_utf8(slice).ok()
1326 }
1327 }
1328
1329 pub fn arg_error(&mut self, arg: Index, extramsg: &str) -> ! {
1331 let c_str = CString::new(extramsg).unwrap();
1333 unsafe { ffi::luaL_argerror(self.L, arg, c_str.as_ptr()) };
1334 unreachable!()
1335 }
1336
1337 pub fn check_number(&mut self, arg: Index) -> Number {
1342 unsafe { ffi::luaL_checknumber(self.L, arg) }
1343 }
1344
1345 pub fn opt_number(&mut self, arg: Index, def: Number) -> Number {
1347 unsafe { ffi::luaL_optnumber(self.L, arg, def) }
1348 }
1349
1350 pub fn check_integer(&mut self, arg: Index) -> Integer {
1352 unsafe { ffi::luaL_checkinteger(self.L, arg) }
1353 }
1354
1355 pub fn opt_integer(&mut self, arg: Index, def: Integer) -> Integer {
1357 unsafe { ffi::luaL_optinteger(self.L, arg, def) }
1358 }
1359
1360 pub fn check_stack_msg(&mut self, sz: c_int, msg: &str) {
1362 let c_str = CString::new(msg).unwrap();
1363 unsafe { ffi::luaL_checkstack(self.L, sz, c_str.as_ptr()) }
1364 }
1365
1366 pub fn check_type(&mut self, arg: Index, t: Type) {
1368 unsafe { ffi::luaL_checktype(self.L, arg, t as c_int) }
1369 }
1370
1371 pub fn check_any(&mut self, arg: Index) {
1373 unsafe { ffi::luaL_checkany(self.L, arg) }
1374 }
1375
1376 pub fn new_metatable(&mut self, tname: &str) -> bool {
1378 let c_str = CString::new(tname).unwrap();
1379 let result = unsafe {
1380 ffi::luaL_newmetatable(self.L, c_str.as_ptr())
1381 };
1382 result != 0
1383 }
1384
1385 pub fn set_metatable_from_registry(&mut self, tname: &str) {
1387 let c_str = CString::new(tname).unwrap();
1388 unsafe { ffi::luaL_setmetatable(self.L, c_str.as_ptr()) }
1389 }
1390
1391 pub fn test_userdata(&mut self, arg: Index, tname: &str) -> *mut c_void {
1393 let c_str = CString::new(tname).unwrap();
1394 unsafe { ffi::luaL_testudata(self.L, arg, c_str.as_ptr()) }
1395 }
1396
1397 pub unsafe fn test_userdata_typed<'a, T>(&'a mut self, arg: Index, tname: &str) -> Option<&'a mut T> {
1400 mem::transmute(self.test_userdata(arg, tname))
1401 }
1402
1403 pub fn check_userdata(&mut self, arg: Index, tname: &str) -> *mut c_void {
1405 let c_str = CString::new(tname).unwrap();
1406 unsafe { ffi::luaL_checkudata(self.L, arg, c_str.as_ptr()) }
1407 }
1408
1409 pub unsafe fn check_userdata_typed<'a, T>(&'a mut self, arg: Index, tname: &str) -> &'a mut T {
1412 mem::transmute(self.check_userdata(arg, tname))
1413 }
1414
1415 pub fn location(&mut self, lvl: c_int) {
1417 unsafe { ffi::luaL_where(self.L, lvl) }
1418 }
1419
1420 pub fn check_option(&mut self, arg: Index, def: Option<&str>, lst: &[&str]) -> usize {
1424 use std::vec::Vec;
1425 use libc::c_char;
1426 let mut vec: Vec<*const c_char> = Vec::with_capacity(lst.len() + 1);
1427 let cstrs: Vec<CString> = lst.iter().map(|ent| CString::new(*ent).unwrap()).collect();
1428 for ent in cstrs.iter() {
1429 vec.push(ent.as_ptr());
1430 }
1431 vec.push(ptr::null());
1432 let result = match def {
1433 Some(def) => unsafe {
1434 let c_str = CString::new(def).unwrap();
1435 ffi::luaL_checkoption(self.L, arg, c_str.as_ptr(), vec.as_ptr())
1436 },
1437 None => unsafe {
1438 ffi::luaL_checkoption(self.L, arg, ptr::null(), vec.as_ptr())
1439 }
1440 };
1441 result as usize
1442 }
1443
1444 pub fn file_result(&mut self, stat: c_int, fname: &str) -> c_int {
1446 let c_str = CString::new(fname).unwrap();
1447 unsafe { ffi::luaL_fileresult(self.L, stat, c_str.as_ptr()) }
1448 }
1449
1450 pub fn exec_result(&mut self, stat: c_int) -> c_int {
1452 unsafe { ffi::luaL_execresult(self.L, stat) }
1453 }
1454
1455 pub fn reference(&mut self, t: Index) -> Reference {
1457 let result = unsafe { ffi::luaL_ref(self.L, t) };
1458 Reference(result)
1459 }
1460
1461 pub fn unreference(&mut self, t: Index, reference: Reference) {
1463 unsafe { ffi::luaL_unref(self.L, t, reference.value()) }
1464 }
1465
1466 pub fn load_filex(&mut self, filename: &str, mode: &str) -> ThreadStatus {
1468 let result = unsafe {
1469 let filename_c_str = CString::new(filename).unwrap();
1470 let mode_c_str = CString::new(mode).unwrap();
1471 ffi::luaL_loadfilex(self.L, filename_c_str.as_ptr(), mode_c_str.as_ptr())
1472 };
1473 ThreadStatus::from_c_int(result)
1474 }
1475
1476 pub fn load_file(&mut self, filename: &str) -> ThreadStatus {
1478 let c_str = CString::new(filename).unwrap();
1479 let result = unsafe {
1480 ffi::luaL_loadfile(self.L, c_str.as_ptr())
1481 };
1482 ThreadStatus::from_c_int(result)
1483 }
1484
1485 pub fn load_bufferx(&mut self, buff: &[u8], name: &str, mode: &str) -> ThreadStatus {
1487 let name_c_str = CString::new(name).unwrap();
1488 let mode_c_str = CString::new(mode).unwrap();
1489 let result = unsafe { ffi::luaL_loadbufferx(self.L, buff.as_ptr() as *const _, buff.len() as size_t, name_c_str.as_ptr(), mode_c_str.as_ptr()) };
1490 ThreadStatus::from_c_int(result)
1491 }
1492
1493 pub fn load_string(&mut self, source: &str) -> ThreadStatus {
1495 let c_str = CString::new(source).unwrap();
1496 let result = unsafe { ffi::luaL_loadstring(self.L, c_str.as_ptr()) };
1497 ThreadStatus::from_c_int(result)
1498 }
1499
1500 pub fn len_direct(&mut self, index: Index) -> Integer {
1504 unsafe { ffi::luaL_len(self.L, index) }
1505 }
1506
1507 pub fn gsub(&mut self, s: &str, p: &str, r: &str) -> &str {
1509 let s_c_str = CString::new(s).unwrap();
1510 let p_c_str = CString::new(p).unwrap();
1511 let r_c_str = CString::new(r).unwrap();
1512 let ptr = unsafe {
1513 ffi::luaL_gsub(self.L, s_c_str.as_ptr(), p_c_str.as_ptr(), r_c_str.as_ptr())
1514 };
1515 let slice = unsafe { CStr::from_ptr(ptr).to_bytes() };
1516 str::from_utf8(slice).unwrap()
1517 }
1518
1519 pub fn set_fns(&mut self, l: &[(&str, Function)], nup: c_int) {
1521 use std::vec::Vec;
1522 let mut reg: Vec<ffi::luaL_Reg> = Vec::with_capacity(l.len() + 1);
1523 let ents: Vec<(CString, Function)> = l.iter().map(|&(s, f)| (CString::new(s).unwrap(), f)).collect();
1524 for &(ref s, f) in ents.iter() {
1525 reg.push(ffi::luaL_Reg {
1526 name: s.as_ptr(),
1527 func: f
1528 });
1529 }
1530 reg.push(ffi::luaL_Reg {name: ptr::null(), func: None});
1531 unsafe { ffi::luaL_setfuncs(self.L, reg.as_ptr(), nup) }
1532 }
1533
1534 pub fn get_subtable(&mut self, idx: Index, fname: &str) -> bool {
1536 let c_str = CString::new(fname).unwrap();
1537 let result = unsafe {
1538 ffi::luaL_getsubtable(self.L, idx, c_str.as_ptr())
1539 };
1540 result != 0
1541 }
1542
1543 pub fn traceback(&mut self, state: &mut State, msg: &str, level: c_int) {
1545 let c_str = CString::new(msg).unwrap();
1546 unsafe { ffi::luaL_traceback(self.L, state.L, c_str.as_ptr(), level) }
1547 }
1548
1549 pub fn requiref(&mut self, modname: &str, openf: Function, glb: bool) {
1551 let c_str = CString::new(modname).unwrap();
1552 unsafe { ffi::luaL_requiref(self.L, c_str.as_ptr(), openf, glb as c_int) }
1553 }
1554
1555 pub fn new_lib_table(&mut self, l: &[(&str, Function)]) {
1557 self.create_table(0, l.len() as c_int)
1558 }
1559
1560 pub fn new_lib(&mut self, l: &[(&str, Function)]) {
1562 self.check_version();
1563 self.new_lib_table(l);
1564 self.set_fns(l, 0)
1565 }
1566
1567 pub fn arg_check(&mut self, cond: bool, arg: Index, extramsg: &str) {
1569 let c_str = CString::new(extramsg).unwrap();
1570 unsafe {
1571 ffi::luaL_argcheck(self.L, cond as c_int, arg, c_str.as_ptr())
1572 }
1573 }
1574
1575 pub fn check_string(&mut self, n: Index) -> &str {
1577 let mut size = 0;
1578 let ptr = unsafe { ffi::luaL_checklstring(self.L, n, &mut size) };
1579 let slice = unsafe { slice::from_raw_parts(ptr as *const u8, size as usize) };
1580 str::from_utf8(slice).unwrap()
1581 }
1582
1583 pub fn opt_string<'a>(&'a mut self, n: Index, default: &'a str) -> &'a str {
1585 let mut size = 0;
1586 let c_str = CString::new(default).unwrap();
1587 let ptr = unsafe { ffi::luaL_optlstring(self.L, n, c_str.as_ptr(), &mut size) };
1588 if ptr == c_str.as_ptr() {
1589 default
1590 } else {
1591 let slice = unsafe { slice::from_raw_parts(ptr as *const u8, size as usize) };
1592 str::from_utf8(slice).unwrap()
1593 }
1594 }
1595
1596 pub fn typename_at(&mut self, n: Index) -> &'static str {
1603 let typeid = self.type_of(n).unwrap();
1604 self.typename_of(typeid)
1605 }
1606
1607 pub fn get_metatable_from_registry(&mut self, tname: &str) {
1611 let c_str = CString::new(tname).unwrap();
1612 unsafe { ffi::luaL_getmetatable(self.L, c_str.as_ptr()) }
1613 }
1614
1615 pub fn load_buffer(&mut self, buff: &[u8], name: &str) -> ThreadStatus {
1619 let name_c_str = CString::new(name).unwrap();
1620 let result = unsafe { ffi::luaL_loadbuffer(self.L, buff.as_ptr() as *const _, buff.len() as size_t, name_c_str.as_ptr()) };
1621 ThreadStatus::from_c_int(result)
1622 }
1623
1624 }
1626
1627impl Drop for State {
1628 fn drop(&mut self) {
1629 if self.owned {
1630 unsafe {
1631 let extra_ptr = ffi::lua_getextraspace(self.L) as ExtraHolder;
1632 ptr::drop_in_place(*extra_ptr);
1633 ffi::lua_close(self.L);
1634 }
1635 }
1636 }
1637}