pub struct Lua { /* private fields */ }Expand description
Data structure that represents a main Lua thread.
Unlike Coroutine,
this data structure has a Drop implementation that automatically closes (frees) the Lua state.
§Thread safety
Lua isn’t Send nor Sync because of Thread, which doesn’t
implement any of those traits either.
Though, this structure owns its Lua thread, so, at first glance, it should
implement Send, but implementing this marker trait is not valid.
Due to the unique nature of most Thread methods which take a &self
instead of a &mut self, a Lua could’ve been put into an Arc<Lua>,
and then internally mutated through the &self methods if it implemented
Send.
§Examples
The Lua headers define there to be the macros lua_lock and lua_unlock.
These macros are intended to be used during compilation to synchronize
operations on a Lua state, possibly with a mutex.
The default definitions for these macros, however, are no-ops and will not
ensure any thread safety by default.
If you are sure that the Lua API you’re linking against has been compiled
with meaningful lua_lock and lua_unlock, then you can wrap a Lua in
another type and implement Send and Sync for it, as well as
Deref and DerefMut for ergonomics:
use core::ops::{ Deref, DerefMut };
use lunka::Lua;
#[repr(transparent)]
pub struct MtLua {
lua: Lua,
}
impl Deref for MtLua {
type Target = Lua;
fn deref(&self) -> &Self::Target {
&self.lua
}
}
impl DerefMut for MtLua {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.lua
}
}
// SAFETY: The Lua API we're linking against was compiled with
// synchronization for mutable operations.
unsafe impl Send for MtLua {}
unsafe impl Sync for MtLua {}
impl MtLua {
pub fn new() -> Self {
let lua = Lua::new();
Self {
lua
}
}
}
let lua = MtLua::new();
assert_eq!(lua.version(), lunka::cdef::VERSION_NUM);Implementations§
Source§impl Lua
impl Lua
Sourcepub fn new_auxlib() -> Self
pub fn new_auxlib() -> Self
Construct a new Lua using the lauxlib function luaL_newstate.
Unlike Lua::try_new_auxlib, this function never fails.
Sourcepub fn try_new_auxlib() -> Option<Self>
pub fn try_new_auxlib() -> Option<Self>
Construct a new Lua using the lauxlib function luaL_newstate.
The function will return None if allocation failed.
Sourcepub unsafe fn new_with_alloc_fn(
alloc_fn: Alloc,
alloc_fn_data: *mut c_void,
) -> Self
pub unsafe fn new_with_alloc_fn( alloc_fn: Alloc, alloc_fn_data: *mut c_void, ) -> Self
Construct a new Lua using an allocation function (see Alloc).
Unlike Lua::try_new_with_alloc_fn, this function never fails.
§Safety
alloc_fn_data must be valid to be passed to alloc_fn.
Sourcepub unsafe fn try_new_with_alloc_fn(
alloc_fn: Alloc,
alloc_fn_data: *mut c_void,
) -> Option<Self>
pub unsafe fn try_new_with_alloc_fn( alloc_fn: Alloc, alloc_fn_data: *mut c_void, ) -> Option<Self>
Sourcepub fn new() -> Self
pub fn new() -> Self
Construct a new Lua using the global Rust allocator,
aligning all allocations to the alignment of MaxAlign.
Unlike Lua::try_new, this function never fails.
Examples found in repository?
More examples
98fn main() -> ExitCode {
99 let mut lua = Lua::new();
100
101 lua.push_c_function(l_main);
102 let status = lua.run_managed(|mut mg| unsafe { mg.pcall(0, 1, 0) });
103 let is_ok = lua.to_boolean(-1);
104 report(&mut lua, status);
105
106 if status.is_ok() && is_ok {
107 ExitCode::SUCCESS
108 } else {
109 ExitCode::FAILURE
110 }
111}41fn main() {
42 let mut lua = Lua::new();
43
44 let did_run_ok = lua.run_managed(move |mut mg| {
45 mg.push_c_function(l_main);
46 if unsafe { mg.pcall(0, 1, 0).is_ok() } {
47 mg.to_boolean(-1)
48 } else {
49 false
50 }
51 });
52 if !did_run_ok {
53 panic!("couldn't run \"Hello, world!\" example for some reason");
54 }
55}63fn main() {
64 let mut lua = Lua::new();
65 lua.run_managed(|mut mg| mg.open_libs());
66
67 if !lua.load_string(PRINT_CODE.as_bytes(), PRINT_CODE_LUA_NAME).is_ok() {
68 panic!("couldn't load Lua chunk");
69 }
70
71 lua.push(4 as LuaInteger);
72 lua.push(3.1 as LuaNumber);
73 lua.push("how");
74
75 if !lua.run_managed(|mut mg| {
76 mg.restart_gc();
77 unsafe { mg.pcall(3, 0, 0) }
78 }).is_ok() {
79 let error_bytes = lua.to_string(-1);
80 panic!(
81 "error while running Lua chunk: {}",
82 error_bytes.map(String::from_utf8_lossy)
83 .unwrap_or(std::borrow::Cow::Borrowed("<no message>"))
84 );
85 }
86}Methods from Deref<Target = Thread>§
Sourcepub fn as_ptr(&self) -> *mut State
pub fn as_ptr(&self) -> *mut State
Return the raw C pointer that represents the underlying Lua state.
Sourcepub fn run_managed<R>(&mut self, func: impl FnOnce(Managed<'_>) -> R) -> R
pub fn run_managed<R>(&mut self, func: impl FnOnce(Managed<'_>) -> R) -> R
Run code that can restart the GC and potentially invalidate pointers in a context.
Examples found in repository?
22fn report(lua: &mut LuaThread, status: LuaStatus) -> bool {
23 if !status.is_ok() {
24 if let Some(message) = lua.to_c_str(-1) {
25 c_eprintln(message);
26 }
27 lua.run_managed(|mut mg| unsafe { mg.pop(1) });
28 false
29 } else {
30 true
31 }
32}
33
34unsafe extern "C-unwind" fn l_err_handler(l: *mut LuaState) -> c_int {
35 let lua = unsafe { LuaThread::from_ptr_mut(l) };
36
37 if let Some(msg) = lua.to_c_str(1) {
38 lua.traceback(lua, Some(msg), 1);
39 return 1
40 }
41
42 let ok = lua.run_managed(|mut mg| unsafe {
43 mg.call_metamethod(1, c"__tostring")
44 });
45
46 if ok && lua.type_of(-1) == LuaType::String {
47 return 1
48 }
49
50 unsafe { lua_push_fmt_string!(lua, c"(error object is a %s value)", lua.type_name_of(1)) };
51
52 1
53}
54
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}
97
98fn main() -> ExitCode {
99 let mut lua = Lua::new();
100
101 lua.push_c_function(l_main);
102 let status = lua.run_managed(|mut mg| unsafe { mg.pcall(0, 1, 0) });
103 let is_ok = lua.to_boolean(-1);
104 report(&mut lua, status);
105
106 if status.is_ok() && is_ok {
107 ExitCode::SUCCESS
108 } else {
109 ExitCode::FAILURE
110 }
111}More examples
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57 let mut test = move |variant: &[u8]| {
58 lua.run_managed(move |mut mg| {
59 mg.push_c_function(l_test);
60 mg.push_string(variant);
61 unsafe { mg.call(1, 0) }
62 })
63 };
64 test(b"udp");
65 test(b"tcp");
66 test(b"unix udp");
67 test(b"unix tcp");
68 test(b"invalid");
69 0
70}
71
72fn main() {
73 let mut lua = Lua::new();
74 let did_run_ok = lua.run_managed(move |mut mg| {
75 mg.push_c_function(l_main);
76 unsafe { mg.pcall(0, 1, 0).is_ok() }
77 });
78 assert!(!did_run_ok, "test code should fail");
79}63fn main() {
64 let mut lua = Lua::new();
65 lua.run_managed(|mut mg| mg.open_libs());
66
67 if !lua.load_string(PRINT_CODE.as_bytes(), PRINT_CODE_LUA_NAME).is_ok() {
68 panic!("couldn't load Lua chunk");
69 }
70
71 lua.push(4 as LuaInteger);
72 lua.push(3.1 as LuaNumber);
73 lua.push("how");
74
75 if !lua.run_managed(|mut mg| {
76 mg.restart_gc();
77 unsafe { mg.pcall(3, 0, 0) }
78 }).is_ok() {
79 let error_bytes = lua.to_string(-1);
80 panic!(
81 "error while running Lua chunk: {}",
82 error_bytes.map(String::from_utf8_lossy)
83 .unwrap_or(std::borrow::Cow::Borrowed("<no message>"))
84 );
85 }
86}6unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
7 let lua = unsafe { LuaThread::from_ptr_mut(l) };
8 lua.run_managed(move |mut mg| mg.open_libs());
9
10 let is_ok = lua.load_string(
11 r#"print("Hello, world!")"#,
12 c"=<embedded>"
13 ).is_ok();
14 if !is_ok {
15 let error = {
16 lua.to_string(-1)
17 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
18 .unwrap_or("<message is not UTF-8>")
19 };
20 eprintln!("couldn't load example Lua code:\n\t{error}");
21 lua.push_boolean(false);
22 return 1
23 }
24
25 let is_ok = lua.run_managed(move |mut mg| unsafe { mg.pcall(0, 0, 0).is_ok() });
26 if !is_ok {
27 let error = {
28 lua.to_string(-1)
29 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
30 .unwrap_or("<message is not UTF-8>")
31 };
32 eprintln!("couldn't run example Lua code:\n\t{error}");
33 lua.push_boolean(false);
34 return 1
35 }
36
37 lua.push_boolean(true);
38 1
39}
40
41fn main() {
42 let mut lua = Lua::new();
43
44 let did_run_ok = lua.run_managed(move |mut mg| {
45 mg.push_c_function(l_main);
46 if unsafe { mg.pcall(0, 1, 0).is_ok() } {
47 mg.to_boolean(-1)
48 } else {
49 false
50 }
51 });
52 if !did_run_ok {
53 panic!("couldn't run \"Hello, world!\" example for some reason");
54 }
55}11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub unsafe fn run_managed_no_gc<R>(
&self,
func: impl FnOnce(Managed<'_>) -> R,
) -> R
pub unsafe fn run_managed_no_gc<R>( &self, func: impl FnOnce(Managed<'_>) -> R, ) -> R
This is the same as Thread::run_managed, however it doesn’t borrow
mutably by assuming that the garbage collector will not collect (and
thus invalidate) any outside references.
§Safety
The body of func must not include any operations that may cause the
garbage collector to run a cycle.
For example, if performing arithmetic on numbers does not trigger any metamethods, or it triggers metamethods that can’t ever cause the collector to collect, then this invariant is not broken.
Sourcepub unsafe fn close_as_main(&mut self)
pub unsafe fn close_as_main(&mut self)
Close all active to-be-closed variables in the main thread, release all
objects (calling the corresponding garbage-collection metamethods, if
any), and free all dynamic memory used by this Thread.
§Safety
This Thread must not be used for any further API calls, as the
underlying Lua pointer becomes invalid after this call.
Sourcepub fn close_as_coroutine(&mut self) -> Status
pub fn close_as_coroutine(&mut self) -> Status
Reset a thread, cleaning its call stack and closing all pending to-be-closed variables.
Returns a status code: Status::Ok for no errors in the thread
(either the original error that stopped the thread or errors in closing
methods), or an error status otherwise.
In case of error, leaves the error object on the top of its own stack.
Sourcepub fn close_as_coroutine_from(&mut self, from: &Self) -> Status
pub fn close_as_coroutine_from(&mut self, from: &Self) -> Status
This behaves similarly to Thread::close_as_coroutine, but allows to specify from,
which represents the coroutine that is resetting this one.
Sourcepub fn at_panic(&self, func: Option<CFunction>) -> Option<CFunction>
pub fn at_panic(&self, func: Option<CFunction>) -> Option<CFunction>
Set a new panic function and return the old one.
Sourcepub fn error(&self) -> !
pub fn error(&self) -> !
Raise a Lua error, using the value on the top of the stack as the error object.
This function does a long jump, and therefore never returns.
Sourcepub fn restart_gc(&self)
pub fn restart_gc(&self)
Restart the garbage collector.
This by itself does not run a collection.
Examples found in repository?
63fn main() {
64 let mut lua = Lua::new();
65 lua.run_managed(|mut mg| mg.open_libs());
66
67 if !lua.load_string(PRINT_CODE.as_bytes(), PRINT_CODE_LUA_NAME).is_ok() {
68 panic!("couldn't load Lua chunk");
69 }
70
71 lua.push(4 as LuaInteger);
72 lua.push(3.1 as LuaNumber);
73 lua.push("how");
74
75 if !lua.run_managed(|mut mg| {
76 mg.restart_gc();
77 unsafe { mg.pcall(3, 0, 0) }
78 }).is_ok() {
79 let error_bytes = lua.to_string(-1);
80 panic!(
81 "error while running Lua chunk: {}",
82 error_bytes.map(String::from_utf8_lossy)
83 .unwrap_or(std::borrow::Cow::Borrowed("<no message>"))
84 );
85 }
86}More examples
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}Sourcepub fn stop_gc(&self)
pub fn stop_gc(&self)
Stop the garbage collector.
Examples found in repository?
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}Sourcepub fn mem_kbytes(&self) -> c_uint
pub fn mem_kbytes(&self) -> c_uint
Return the current amount of memory (in kilobytes) in use by this Thread.
Sourcepub fn mem_byte_remainder(&self) -> c_uint
pub fn mem_byte_remainder(&self) -> c_uint
Return the remainder of dividing the current amount of bytes of memory in use by this Thread by 1024.
Sourcepub fn is_gc_running(&self) -> bool
pub fn is_gc_running(&self) -> bool
Return true if the collector is running (i.e. not stopped).
Sourcepub fn switch_gc_to(&mut self, gc: GcMode)
pub fn switch_gc_to(&mut self, gc: GcMode)
Change the collector to either incremental or generational mode (see also GcMode) with the given parameters.
Sourcepub fn abs_index(&self, idx: c_int) -> c_int
pub fn abs_index(&self, idx: c_int) -> c_int
Convert the acceptable index idx into an equivalent absolute index
(that is, one that does not depend on the stack size).
Sourcepub fn test_stack(&self, n: c_uint) -> bool
pub fn test_stack(&self, n: c_uint) -> bool
Ensure that the stack has space for at least n extra elements.
That is, that you can safely push up to n values into it.
Returns false if it cannot fulfill the request, either because it
would cause the stack to be greater than a fixed maximum size (typically
at least several thousand elements) or because it cannot allocate memory
for the extra space.
This function never shrinks the stack; if the stack already has space for the extra elements, it is left unchanged.
Sourcepub fn copy(&self, from_idx: c_int, to_idx: c_int)
pub fn copy(&self, from_idx: c_int, to_idx: c_int)
Copy the element at from_idx into the valid index to_idx, replacing
the value at that position.
Values at other positions are not affected.
Sourcepub fn create_table(&self, n_arr: c_uint, n_rec: c_uint)
pub fn create_table(&self, n_arr: c_uint, n_rec: c_uint)
Create a new empty table and push it onto the stack.
narr is a hint for how many elements the table will have as a sequence,
and nrec is a hint for how many other elements the table will have.
Lua may use these hints to preallocate memory for the new table.
This preallocation may help performance when its known in advance how
many elements the table will have.
See also Thread::new_table.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub unsafe fn dump(
&self,
writer: Writer,
writer_data: *mut c_void,
strip_debug_info: bool,
) -> c_int
pub unsafe fn dump( &self, writer: Writer, writer_data: *mut c_void, strip_debug_info: bool, ) -> c_int
Dump a function as a binary chunk, and return the status of the operation.
This function receives a Lua function on the top of the stack and produces a binary chunk that, if loaded again, results in a function equivalent to the one dumped.
As it produces parts of the chunk, the function calls writer (see also
Writer) with the given data to write them.
If strip_debug_info is true, the binary representation may not
include all debug information about the function, to save space.
The value returned is the error code returned by the last call to the writer.
This function does not pop the Lua function from the stack.
§Safety
writer_data must be valid to be passed to writer.
Sourcepub fn get_alloc_fn(&self) -> (Alloc, *mut c_void)
pub fn get_alloc_fn(&self) -> (Alloc, *mut c_void)
Return the memory-allocation function of this Thread along with the
opaque pointer given when the memory-allocator function was set.
Sourcepub fn get_global(&self, name: &CStr) -> Type
pub fn get_global(&self, name: &CStr) -> Type
Sourcepub fn get_i_uservalue(&self, ud_index: c_int, n: c_int) -> Type
pub fn get_i_uservalue(&self, ud_index: c_int, n: c_int) -> Type
Push onto the stack the n-th user value associated with the full
userdata at the given index and returns the type of the pushed value.
If the userdata does not have that value, push nil and return Type::None.
Sourcepub fn get_metatable(&self, obj_index: c_int) -> bool
pub fn get_metatable(&self, obj_index: c_int) -> bool
If the value at the given index has a metatable, push that metatable
onto the stack and return true. Otherwise, push nothing and return
false.
Sourcepub fn top(&self) -> c_int
pub fn top(&self) -> c_int
Return the index of the top element in the stack.
Because indices start at 1, this result is equal to the number of
elements in the stack; in particular, 0 means an empty stack.
Examples found in repository?
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}Sourcepub fn insert(&self, index: c_int)
pub fn insert(&self, index: c_int)
Move the top element into the given valid index, shifting up the elements above that index to open space.
This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.
Sourcepub fn is_boolean(&self, index: c_int) -> bool
pub fn is_boolean(&self, index: c_int) -> bool
Return true if the value at the given index is a boolean.
Sourcepub fn is_c_function(&self, index: c_int) -> bool
pub fn is_c_function(&self, index: c_int) -> bool
Return true if the value at the given index is a C function.
Sourcepub fn is_function(&self, index: c_int) -> bool
pub fn is_function(&self, index: c_int) -> bool
Return true if the value at the given index is a function (either
C or Lua).
Sourcepub fn is_integer(&self, index: c_int) -> bool
pub fn is_integer(&self, index: c_int) -> bool
Return true if the value at the given index is an integer.
Sourcepub fn is_light_userdata(&self, index: c_int) -> bool
pub fn is_light_userdata(&self, index: c_int) -> bool
Return true if the value at the given index is a light userdata.
Sourcepub fn is_none(&self, index: c_int) -> bool
pub fn is_none(&self, index: c_int) -> bool
Return true if the value at the given index is not valid.
Sourcepub fn is_none_or_nil(&self, index: c_int) -> bool
pub fn is_none_or_nil(&self, index: c_int) -> bool
Return true if the value at the given index is not valid or is
nil.
Sourcepub fn is_number(&self, index: c_int) -> bool
pub fn is_number(&self, index: c_int) -> bool
Return true if the value at the given index is a number.
Sourcepub fn is_string(&self, index: c_int) -> bool
pub fn is_string(&self, index: c_int) -> bool
Return true if the value at the given index is a string or a
number, which is always convertible to a string.
Sourcepub fn is_table(&self, index: c_int) -> bool
pub fn is_table(&self, index: c_int) -> bool
Return true if the value at the given index is a table.
Sourcepub fn is_thread(&self, index: c_int) -> bool
pub fn is_thread(&self, index: c_int) -> bool
Return true if the value at the given index is a thread.
Sourcepub fn is_userdata(&self, index: c_int) -> bool
pub fn is_userdata(&self, index: c_int) -> bool
Return true if the value at the given index is a userdata (either
full or light).
Sourcepub unsafe fn load(
&self,
reader: Reader,
reader_data: *mut c_void,
chunk_name: &CStr,
mode: Option<&CStr>,
) -> Status
pub unsafe fn load( &self, reader: Reader, reader_data: *mut c_void, chunk_name: &CStr, mode: Option<&CStr>, ) -> Status
Load a Lua chunk without running it.
If there are no errors, push the compiled chunk as a Lua function. Otherwise, push an error message.
This function uses a user-supplied reader to read the chunk (see also
Reader).
reader_data is an opaque value passed to the reader function.
chunk_name gives a name to the chunk, which is used for error messages
and in debug information.
The function automatically detects whether the chunk is text or binary
and loads it accordingly.
The string mode works similarly as in the Lua base library function
load:
Some("b")loads only binary chunks.Some("t")loads only text chunks.Some("bt")loads both binary and text chunks.Noneis equivalent to the string"bt".
This function uses the stack internally, so reader must always leave
the stack unmodified when returning.
If the resulting function has upvalues, its first upvalue is set to the
value of the global environment stored at index REGISTRY_GLOBALS in
the registry.
When loading main chunks, this upvalue will be the _ENV variable.
Other upvalues are initialized with nil.
§Safety
reader_data must be valid to be passed to reader.
Sourcepub fn new_table(&self)
pub fn new_table(&self)
Create a new empty table and push it onto the stack.
See also Thread::create_table.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn new_thread(&self) -> Coroutine<'_>
pub fn new_thread(&self) -> Coroutine<'_>
Create a new thread, push it on the stack, and return a Coroutine
that represents this new thread.
The new thread returned by this function shares with the original thread its global environment, but has an independent execution stack. Threads are subject to garbage collection, like any Lua object.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub unsafe fn new_userdata_raw(
&self,
size: usize,
n_uservalues: c_int,
) -> *mut c_void
pub unsafe fn new_userdata_raw( &self, size: usize, n_uservalues: c_int, ) -> *mut c_void
Create and push on the stack a new full userdata, with n_uservalues
associated Lua values, called user values, and an associated block of
raw memory of size bytes.
The function returns a pointer to the block of memory that was allocated by Lua.
The user values can be set and read with the functions
Thread::set_i_uservalue and Thread::get_i_uservalue.
You may use this function if, for instance, the layout of the data in the allocation changes based on run-time information.
§Errors
The underlying Lua state may raise a memory error.
§Safety
Lua ensures that the pointer is valid as long as the corresponding userdata is alive. Moreover, if the userdata is marked for finalization, it is valid at least until the call to its finalizer. The returned pointer must only be used while it’s valid.
Lua makes no guarantees about the alignment of the pointer. It depends entirely on the allocator function used.
Sourcepub fn next(&self, index: c_int) -> bool
pub fn next(&self, index: c_int) -> bool
Pop a key from the stack, and push a key–value pair from the table at the given index, the “next” pair after the given key.
This function returns true while there are still elements to go
through. If there are no more elements in the table, then this it
returns false and pushes nothing.
§Note on string conversion functions
While traversing a table, avoid calling Thread::to_c_chars directly
on a key, unless it is known that the key is actually a string.
Thread::to_c_chars and other similar functions may change the value
at the given index; this confuses the next call to Thread::next.
§Errors
The underlying Lua state may raise an error
if a given key is neither nil nor present in the table.
Sourcepub fn push_boolean(&self, value: bool)
pub fn push_boolean(&self, value: bool)
Push a bool onto the stack.
Examples found in repository?
6unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
7 let lua = unsafe { LuaThread::from_ptr_mut(l) };
8 lua.run_managed(move |mut mg| mg.open_libs());
9
10 let is_ok = lua.load_string(
11 r#"print("Hello, world!")"#,
12 c"=<embedded>"
13 ).is_ok();
14 if !is_ok {
15 let error = {
16 lua.to_string(-1)
17 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
18 .unwrap_or("<message is not UTF-8>")
19 };
20 eprintln!("couldn't load example Lua code:\n\t{error}");
21 lua.push_boolean(false);
22 return 1
23 }
24
25 let is_ok = lua.run_managed(move |mut mg| unsafe { mg.pcall(0, 0, 0).is_ok() });
26 if !is_ok {
27 let error = {
28 lua.to_string(-1)
29 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
30 .unwrap_or("<message is not UTF-8>")
31 };
32 eprintln!("couldn't run example Lua code:\n\t{error}");
33 lua.push_boolean(false);
34 return 1
35 }
36
37 lua.push_boolean(true);
38 1
39}More examples
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}Sourcepub fn push_c_closure(&self, func: CFunction, n_upvalues: c_int)
pub fn push_c_closure(&self, func: CFunction, n_upvalues: c_int)
Push a new C closure onto the stack.
This function receives a C function func and pushes onto the stack a
Lua value of type function that, when called, invokes the
corresponding C function.
n_upvalues tells how many upvalues this function will have.
Any function to be callable by Lua must follow the correct protocol to
receive its parameters and return its results (see CFunction).
§C closures
When a C function is created, it is possible to associate some values with it, which are called upvalues. These upvalues are then accessible to the function whenever it is called, where the function is called a C closure. To create a C closure:
- Push the initial values for its upvalues onto the stack. (When there are multiple upvalues, the first value is pushed first.)
- Call this function with the argument
n_upvaluestelling how many upvalues will be associated with the function. The function will also pop these values from the stack.
When n_upvalues == 0, this function creates a “light” C function,
which is just a pointer to the C function. In that case, it never raises
a memory error.
See also Thread::push_c_function.
§Errors
The underlying Lua state may raise a memory error if n_upvalues > 0.
Sourcepub fn push_c_function(&self, func: CFunction)
pub fn push_c_function(&self, func: CFunction)
Push a light C function onto the stack (that is, a C function with no upvalues).
See also Thread::push_c_closure.
Examples found in repository?
41fn main() {
42 let mut lua = Lua::new();
43
44 let did_run_ok = lua.run_managed(move |mut mg| {
45 mg.push_c_function(l_main);
46 if unsafe { mg.pcall(0, 1, 0).is_ok() } {
47 mg.to_boolean(-1)
48 } else {
49 false
50 }
51 });
52 if !did_run_ok {
53 panic!("couldn't run \"Hello, world!\" example for some reason");
54 }
55}More examples
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57 let mut test = move |variant: &[u8]| {
58 lua.run_managed(move |mut mg| {
59 mg.push_c_function(l_test);
60 mg.push_string(variant);
61 unsafe { mg.call(1, 0) }
62 })
63 };
64 test(b"udp");
65 test(b"tcp");
66 test(b"unix udp");
67 test(b"unix tcp");
68 test(b"invalid");
69 0
70}
71
72fn main() {
73 let mut lua = Lua::new();
74 let did_run_ok = lua.run_managed(move |mut mg| {
75 mg.push_c_function(l_main);
76 unsafe { mg.pcall(0, 1, 0).is_ok() }
77 });
78 assert!(!did_run_ok, "test code should fail");
79}55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}
97
98fn main() -> ExitCode {
99 let mut lua = Lua::new();
100
101 lua.push_c_function(l_main);
102 let status = lua.run_managed(|mut mg| unsafe { mg.pcall(0, 1, 0) });
103 let is_ok = lua.to_boolean(-1);
104 report(&mut lua, status);
105
106 if status.is_ok() && is_ok {
107 ExitCode::SUCCESS
108 } else {
109 ExitCode::FAILURE
110 }
111}Sourcepub fn push_global_table(&self)
pub fn push_global_table(&self)
Push the global environment onto the stack.
Sourcepub fn push_integer(&self, value: Integer)
pub fn push_integer(&self, value: Integer)
Push an Integer onto the stack.
Examples found in repository?
More examples
11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub unsafe fn push_light_userdata(&self, ptr: *mut c_void)
pub unsafe fn push_light_userdata(&self, ptr: *mut c_void)
Push a light userdata onto the stack.
A light userdata represents a plain pointer. It is a value, like a number: it is not created, it has no individual metatable, and it is not collected (as it was never created).
A light userdata is equal to any light userdata with the same C address.
§Safety
ptr can be used arbitrarily in Lua,
so this method should only be used for trusted code.
Sourcepub fn push_c_chars<'l>(&'l self, data: &[c_char]) -> &'l [c_char]
pub fn push_c_chars<'l>(&'l self, data: &[c_char]) -> &'l [c_char]
Works the same as Thread::push_string, however it accepts
c_chars instead of u8s.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn push_string(&self, data: impl AsRef<[u8]>) -> &[u8]
pub fn push_string(&self, data: impl AsRef<[u8]>) -> &[u8]
Push a string onto the stack.
The string can contain any binary data, including embedded zeros.
Lua will make or reuse an internal copy of the given string, so the
memory pointed to by data can be safely freed or reused immediately
after the function returns.
See also Thread::push_c_chars.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
More examples
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57 let mut test = move |variant: &[u8]| {
58 lua.run_managed(move |mut mg| {
59 mg.push_c_function(l_test);
60 mg.push_string(variant);
61 unsafe { mg.call(1, 0) }
62 })
63 };
64 test(b"udp");
65 test(b"tcp");
66 test(b"unix udp");
67 test(b"unix tcp");
68 test(b"invalid");
69 0
70}55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}4unsafe extern "C-unwind" fn l_hello(l: *mut LuaState) -> c_int {
5 // SAFETY: Caller ensures `l` is valid.
6 let lua = unsafe { LuaThread::from_ptr(l) };
7
8 let n = lua.check_number(1);
9
10 // SAFETY: Ditto.
11 lua.push_string("Hello, world!");
12 lua.push_number(n * core::f64::consts::PI as LuaNumber);
13
14 2
15}11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub fn push_nil(&self)
pub fn push_nil(&self)
Push nil onto the stack.
Examples found in repository?
15 fn push_into(&self, thread: &LuaThread) {
16 thread.push_nil();
17 }
18}
19
20impl Push<1> for LuaInteger {
21 fn push_into(&self, thread: &LuaThread) {
22 thread.push_integer(*self);
23 }
24}
25
26impl Push<1> for LuaNumber {
27 fn push_into(&self, thread: &LuaThread) {
28 thread.push_number(*self);
29 }
30}
31
32impl Push<1> for &str {
33 fn push_into(&self, thread: &LuaThread) {
34 thread.push_string(self.as_bytes());
35 }
36}
37
38impl<T: Push<1>, E: Push<1>> Push<2> for Result<T, E> {
39 fn push_into(&self, thread: &LuaThread) {
40 match self {
41 Self::Ok(t) => {
42 t.push_into(thread);
43 thread.push_nil()
44 }
45 Self::Err(e) => {
46 thread.push_fail();
47 e.push_into(thread)
48 }
49 }
50 }Sourcepub fn push_number(&self, value: Number)
pub fn push_number(&self, value: Number)
Push a Number onto the stack.
Examples found in repository?
More examples
4unsafe extern "C-unwind" fn l_hello(l: *mut LuaState) -> c_int {
5 // SAFETY: Caller ensures `l` is valid.
6 let lua = unsafe { LuaThread::from_ptr(l) };
7
8 let n = lua.check_number(1);
9
10 // SAFETY: Ditto.
11 lua.push_string("Hello, world!");
12 lua.push_number(n * core::f64::consts::PI as LuaNumber);
13
14 2
15}11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub fn push_c_str<'l>(&'l self, data: &CStr) -> &'l CStr
pub fn push_c_str<'l>(&'l self, data: &CStr) -> &'l CStr
Push a zero-terminated string onto the stack.
Lua will make or reuse an internal copy of the given string, so the
memory pointed to by data can be freed or reused immediately after the
function returns.
See also Thread::push_c_chars and Thread::push_string.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn push_thread(&self) -> bool
pub fn push_thread(&self) -> bool
Sourcepub fn push_value(&self, index: c_int)
pub fn push_value(&self, index: c_int)
Push a copy of the element at the given index onto the stack.
Sourcepub fn raw_equal(&self, idx_a: c_int, idx_b: c_int) -> bool
pub fn raw_equal(&self, idx_a: c_int, idx_b: c_int) -> bool
Return true if the two values in indices idx_a and idx_b are
primitively equal (that is, equal without calling the __eq metamethod).
This also returns false if any of the indices are not valid.
Sourcepub unsafe fn raw_get(&self, tbl_index: c_int) -> Type
pub unsafe fn raw_get(&self, tbl_index: c_int) -> Type
Without calling metamethods, push t[k], where t is the value at the
given index and k is the value on the top of the stack.
§Safety
The value at tbl_index must be a table.
Sourcepub unsafe fn raw_get_i(&self, tbl_index: c_int, i: Integer) -> Type
pub unsafe fn raw_get_i(&self, tbl_index: c_int, i: Integer) -> Type
Without calling metamethods, push t[i], where t is the value at the
given index.
§Safety
The value at tbl_index must be a table.
Sourcepub unsafe fn raw_get_p(&self, tbl_index: c_int, ptr: *const c_void) -> Type
pub unsafe fn raw_get_p(&self, tbl_index: c_int, ptr: *const c_void) -> Type
Without calling metamethods, push t[ptr], where t is the value at
the given index and ptr is the given pointer represented as a light
userdata.
§Safety
The value at tbl_index must be a table.
Sourcepub fn raw_length(&self, index: c_int) -> Unsigned
pub fn raw_length(&self, index: c_int) -> Unsigned
Return the raw “length” of the value at the given index.
For strings, this is the string length;
for tables, this is the result of the length operator (#) with no
metamethods;
for userdata, this is the size of the block of memory allocated for the
userdata.
For other values, this call returns 0.
Sourcepub fn remove(&self, index: c_int)
pub fn remove(&self, index: c_int)
Remove the element at the given valid index, shifting down the elements above this index to fill the gap.
This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.
Sourcepub fn replace(&self, index: c_int)
pub fn replace(&self, index: c_int)
Move the top element into the given valid index without shifting any element (therefore replacing the value at that given index), and then pop that top element.
Sourcepub fn rotate(&self, index: c_int, n_values: c_int)
pub fn rotate(&self, index: c_int, n_values: c_int)
Rotate the stack elements between the valid index index and the top of
the stack.
The elements are rotated n positions in the direction of the top for a
ositive n, or -n positions in the direction of the bottom for a
negative n.
The absolute value of n must not be greater than the size of the slice
being rotated.
This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.
Sourcepub fn set_global(&self, key: &CStr)
pub fn set_global(&self, key: &CStr)
Sourcepub fn set_i_uservalue(&self, ud_index: c_int, n: c_int) -> bool
pub fn set_i_uservalue(&self, ud_index: c_int, n: c_int) -> bool
Pop a value from the stack and set it as the new n-th user value
associated to the full userdata at the given index.
Returns false if the userdata does not have that value.
Sourcepub fn set_metatable(&self, obj_index: c_int)
pub fn set_metatable(&self, obj_index: c_int)
Pop a table or nil from the stack and sets that value as the new
metatable for the value at the given index. (nil means no metatable.)
Sourcepub unsafe fn set_warn_fn(&self, warn: WarnFunction, warn_data: *mut c_void)
pub unsafe fn set_warn_fn(&self, warn: WarnFunction, warn_data: *mut c_void)
Set the warning function to be used by Lua to emit warnings
(see WarnFunction).
See also Thread::remove_warn_fn.
§Safety
warn_data is the custom data to be passed to the warning function.
It must be valid for warn.
Sourcepub fn remove_warn_fn(&self)
pub fn remove_warn_fn(&self)
Remove the warning function to be used by Lua to emit warnings.
See also Thread::set_warn_fn.
Sourcepub fn status(&self) -> Status
pub fn status(&self) -> Status
Return the status of the Lua thread represented by this Thread.
The status can be Status::Ok for a normal thread, an error variant
if the thread finished the execution of a Managed::resume with an
error, or Status::Yielded if the thread is suspended.
Functions can only be called in threads with status Status::Ok.
Threads with status Status::Ok or Status::Yielded can be resumed
(to start a new coroutine or resume an existing one).
Sourcepub fn to_boolean(&self, idx: c_int) -> bool
pub fn to_boolean(&self, idx: c_int) -> bool
Convert the Lua value at the given index to a bool.
Like all tests in Lua, this returns true for any Lua value different
from false and nil; otherwise it returns false.
If you want to accept only actual boolean values, use
Thread::is_boolean to test the value’s type first.
Examples found in repository?
98fn main() -> ExitCode {
99 let mut lua = Lua::new();
100
101 lua.push_c_function(l_main);
102 let status = lua.run_managed(|mut mg| unsafe { mg.pcall(0, 1, 0) });
103 let is_ok = lua.to_boolean(-1);
104 report(&mut lua, status);
105
106 if status.is_ok() && is_ok {
107 ExitCode::SUCCESS
108 } else {
109 ExitCode::FAILURE
110 }
111}More examples
41fn main() {
42 let mut lua = Lua::new();
43
44 let did_run_ok = lua.run_managed(move |mut mg| {
45 mg.push_c_function(l_main);
46 if unsafe { mg.pcall(0, 1, 0).is_ok() } {
47 mg.to_boolean(-1)
48 } else {
49 false
50 }
51 });
52 if !did_run_ok {
53 panic!("couldn't run \"Hello, world!\" example for some reason");
54 }
55}Sourcepub fn to_c_function(&self, index: c_int) -> Option<CFunction>
pub fn to_c_function(&self, index: c_int) -> Option<CFunction>
Convert a value at the given index to a C function.
If it is not one, return None.
Sourcepub unsafe fn to_close(&self, index: c_int)
pub unsafe fn to_close(&self, index: c_int)
Mark the given index in the stack as a to-be-closed slot.
Like a to-be-closed variable in Lua, the value at that slot in the stack
will be closed when it goes out of scope.
Here, in the context of a C function, to go out of scope means that the
running function returns to Lua, or there is an error, or the slot is
removed from the stack through Managed::set_top or Managed::pop,
or there is a call to Managed::close_slot.
A slot marked as to-be-closed should not be removed from the stack by
any other function in the API except Managed::set_top or
Managed::pop, unless previously deactivated by Managed::close_slot.
§Errors
The underlying Lua state may raise a memory error.
§Safety
This function should not be called for an index that is equal to or below an active to-be-closed slot.
Note that, both in case of errors and of a regular return, by the time
the __close metamethod runs, the C stack was already unwound, so that
any automatic C variable declared in the calling function
(e.g., a buffer) will be out of scope.
Sourcepub fn to_integer(&self, idx: c_int) -> Integer
pub fn to_integer(&self, idx: c_int) -> Integer
This behaves exactly the same as Thread::to_integer_opt, however the
return value is 0 if an integer isn’t present.
Sourcepub fn to_integer_opt(&self, idx: c_int) -> Option<Integer>
pub fn to_integer_opt(&self, idx: c_int) -> Option<Integer>
Convert the Lua value at the given index to the signed integral type
Integer.
The Lua value must be an integer, or a number or string convertible to
an integer. Otherwise, this function returns None.
Sourcepub fn to_c_chars(&self, index: c_int) -> Option<&[c_char]>
pub fn to_c_chars(&self, index: c_int) -> Option<&[c_char]>
Convert the Lua value at the given index to a slice of c_chars,
representing a Lua string.
This function works like Thread::to_string.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn to_c_str(&self, index: c_int) -> Option<&CStr>
pub fn to_c_str(&self, index: c_int) -> Option<&CStr>
Convert the Lua value at the given index to a CStr,
representing a Lua string.
This function works like Thread::to_string.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
22fn report(lua: &mut LuaThread, status: LuaStatus) -> bool {
23 if !status.is_ok() {
24 if let Some(message) = lua.to_c_str(-1) {
25 c_eprintln(message);
26 }
27 lua.run_managed(|mut mg| unsafe { mg.pop(1) });
28 false
29 } else {
30 true
31 }
32}
33
34unsafe extern "C-unwind" fn l_err_handler(l: *mut LuaState) -> c_int {
35 let lua = unsafe { LuaThread::from_ptr_mut(l) };
36
37 if let Some(msg) = lua.to_c_str(1) {
38 lua.traceback(lua, Some(msg), 1);
39 return 1
40 }
41
42 let ok = lua.run_managed(|mut mg| unsafe {
43 mg.call_metamethod(1, c"__tostring")
44 });
45
46 if ok && lua.type_of(-1) == LuaType::String {
47 return 1
48 }
49
50 unsafe { lua_push_fmt_string!(lua, c"(error object is a %s value)", lua.type_name_of(1)) };
51
52 1
53}Sourcepub fn to_string(&self, index: c_int) -> Option<&[u8]>
pub fn to_string(&self, index: c_int) -> Option<&[u8]>
Convert the Lua value at the given index to a slice of u8s,
representing a Lua string.
The Lua value must be a string or a number; otherwise, the function
returns None.
If the value is a number, then this function also changes the actual value in the stack to a string.
The function returns a slice to data inside the Lua state.
This string always has a zero ('\0') after its last character (as in C),
but can contain other zeros in its body.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
63fn main() {
64 let mut lua = Lua::new();
65 lua.run_managed(|mut mg| mg.open_libs());
66
67 if !lua.load_string(PRINT_CODE.as_bytes(), PRINT_CODE_LUA_NAME).is_ok() {
68 panic!("couldn't load Lua chunk");
69 }
70
71 lua.push(4 as LuaInteger);
72 lua.push(3.1 as LuaNumber);
73 lua.push("how");
74
75 if !lua.run_managed(|mut mg| {
76 mg.restart_gc();
77 unsafe { mg.pcall(3, 0, 0) }
78 }).is_ok() {
79 let error_bytes = lua.to_string(-1);
80 panic!(
81 "error while running Lua chunk: {}",
82 error_bytes.map(String::from_utf8_lossy)
83 .unwrap_or(std::borrow::Cow::Borrowed("<no message>"))
84 );
85 }
86}More examples
6unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
7 let lua = unsafe { LuaThread::from_ptr_mut(l) };
8 lua.run_managed(move |mut mg| mg.open_libs());
9
10 let is_ok = lua.load_string(
11 r#"print("Hello, world!")"#,
12 c"=<embedded>"
13 ).is_ok();
14 if !is_ok {
15 let error = {
16 lua.to_string(-1)
17 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
18 .unwrap_or("<message is not UTF-8>")
19 };
20 eprintln!("couldn't load example Lua code:\n\t{error}");
21 lua.push_boolean(false);
22 return 1
23 }
24
25 let is_ok = lua.run_managed(move |mut mg| unsafe { mg.pcall(0, 0, 0).is_ok() });
26 if !is_ok {
27 let error = {
28 lua.to_string(-1)
29 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
30 .unwrap_or("<message is not UTF-8>")
31 };
32 eprintln!("couldn't run example Lua code:\n\t{error}");
33 lua.push_boolean(false);
34 return 1
35 }
36
37 lua.push_boolean(true);
38 1
39}Sourcepub fn to_number(&self, idx: c_int) -> Number
pub fn to_number(&self, idx: c_int) -> Number
This behaves exactly the same as Thread::to_number_opt, however the
return value is 0.0 if a number isn’t present.
Sourcepub fn to_number_opt(&self, idx: c_int) -> Option<Number>
pub fn to_number_opt(&self, idx: c_int) -> Option<Number>
Convert the Lua value at the given index to the floating-point number
type Number.
The Lua value must be a number or string convertible to a number.
Otherwise, this function returns None.
Sourcepub fn to_pointer(&self, idx: c_int) -> *const c_void
pub fn to_pointer(&self, idx: c_int) -> *const c_void
Convert the value at the given index to a generic C pointer
(*const c_void).
The value can be a userdata, a table, a thread, a string, or a function; otherwise, this function returns null.
Different objects will give different pointers. There is no way to convert the pointer back to its original value.
Typically this function is used only for hashing and debug information.
Sourcepub fn to_thread(&self, index: c_int) -> *mut State
pub fn to_thread(&self, index: c_int) -> *mut State
Convert the value at the given index to a Lua thread, represented by a
*mutState.
The value must be a thread; otherwise, the function returns null.
Sourcepub fn to_userdata(&self, idx: c_int) -> *mut c_void
pub fn to_userdata(&self, idx: c_int) -> *mut c_void
If the value at the given index is a light or full userdata, return the address it represents. Otherwise, return null.
Sourcepub fn type_of(&self, idx: c_int) -> Type
pub fn type_of(&self, idx: c_int) -> Type
Return the type of the value in the given valid index, or Type::None
for a non-valid but acceptable index.
Examples found in repository?
34unsafe extern "C-unwind" fn l_err_handler(l: *mut LuaState) -> c_int {
35 let lua = unsafe { LuaThread::from_ptr_mut(l) };
36
37 if let Some(msg) = lua.to_c_str(1) {
38 lua.traceback(lua, Some(msg), 1);
39 return 1
40 }
41
42 let ok = lua.run_managed(|mut mg| unsafe {
43 mg.call_metamethod(1, c"__tostring")
44 });
45
46 if ok && lua.type_of(-1) == LuaType::String {
47 return 1
48 }
49
50 unsafe { lua_push_fmt_string!(lua, c"(error object is a %s value)", lua.type_name_of(1)) };
51
52 1
53}Sourcepub fn type_name(&self, type_tag: Type) -> &CStr
pub fn type_name(&self, type_tag: Type) -> &CStr
Return the name of the type encoded by type_tag.
Sourcepub fn warning(&self, message: &CStr, to_be_continued: bool)
pub fn warning(&self, message: &CStr, to_be_continued: bool)
Emit a warning with the given message.
A message in a call with to_be_continued == true should be continued
in another call to this function.
Sourcepub fn xmove(&self, to: &Self, n_values: c_uint)
pub fn xmove(&self, to: &Self, n_values: c_uint)
Exchange values between different threads of the same state.
This function pops n_values values from the stack of this thread, and
pushes them onto the stack of the thread to.
Sourcepub unsafe fn yield_with(&self, n_results: c_int) -> !
pub unsafe fn yield_with(&self, n_results: c_int) -> !
This behaves exactly like Thread::yield_k_with, however there is no
continuation.
§Safety
This function should be called only outside of hooks. It is Undefined Behavior if the code after a call to this function is reachable.
Sourcepub unsafe fn yield_in_hook_with(&self, n_results: c_int)
pub unsafe fn yield_in_hook_with(&self, n_results: c_int)
This behaves exactly like Thread::yield_in_hook_k_with, however
there is no continuation.
§Safety
This function should be called only outside of hooks. It is Undefined Behavior if the code after a call to this function is unreachable.
Sourcepub unsafe fn yield_k_with(
&self,
n_results: c_int,
continuation: KFunction,
context: KContext,
) -> !
pub unsafe fn yield_k_with( &self, n_results: c_int, continuation: KFunction, context: KContext, ) -> !
Yield this thread (like a coroutine).
When this function is called, the running coroutine suspends its
execution, and the call to Managed::resume that started this
coroutine returns.
The parameter n_results is the number of values from the stack that
will be passed as results to Managed::resume.
When the coroutine is resumed again, Lua calls the given continuation
function continuation to continue the execution of the C function that
yielded.
This continuation function receives the same stack from the previous
function, with the n_results results removed and replaced by the
arguments passed to Managed::resume.
Moreover, the continuation function receives the value context that
was originally passed.
Usually, this function does not return; when the coroutine eventually
resumes, it continues executing the continuation function.
However, there is one special case, which is when this function is
called from inside a line or a count hook (see Hook).
In that case, Thread::yield_in_hook_with should be called
(thus, no continuation) and no results, and the hook should return
immediately after the call.
Lua will yield and, when the coroutine resumes again, it will continue
the normal execution of the (Lua) function that triggered the hook.
§Errors
The underlying Lua thread can raise an error if the function is called from a thread with a pending C call with no continuation function (what is called a C-call boundary), or it is called from a thread that is not running inside a resume (typically the main thread).
§Safety
This function should be called only outside of hooks. It is Undefined Behavior if the code after a call to this function is reachable.
Sourcepub unsafe fn yield_in_hook_k_with(
&self,
n_results: c_int,
continuation: KFunction,
context: KContext,
)
pub unsafe fn yield_in_hook_k_with( &self, n_results: c_int, continuation: KFunction, context: KContext, )
This behaves exactly like Thread::yield_k_with, however it should
only be called in hooks.
§Errors
The underlying Lua thread can raise an error if the function is called from a thread with a pending C call with no continuation function (what is called a C-call boundary), or it is called from a thread that is not running inside a resume (typically the main thread).
§Safety
This function should be called only inside of hooks.
Sourcepub unsafe fn debug<const ID_SIZE: usize>(&self) -> ThreadDebug<'_, ID_SIZE>
pub unsafe fn debug<const ID_SIZE: usize>(&self) -> ThreadDebug<'_, ID_SIZE>
Returns a ThreadDebug structure that exposes various functions operating on Debug structures.
§Safety
ID_SIZE must be the appropriate identifier size for the underlying Lua state.
See DEFAULT_ID_SIZE for the default.
Sourcepub fn hook_count(&self) -> c_int
pub fn hook_count(&self) -> c_int
Return the current hook count.
Sourcepub fn get_upvalue(&self, func_index: c_int, n: u8) -> Option<&CStr>
pub fn get_upvalue(&self, func_index: c_int, n: u8) -> Option<&CStr>
Get information about the n-th upvalue of the closure at index
func_index.
This function pushes the upvalue’s value onto the stack and returns its
name. Returns None (and pushes nothing) when the index n is greater
than the number of upvalues.
Sourcepub fn set_upvalue(&self, func_index: c_int, n: u8) -> Option<&CStr>
pub fn set_upvalue(&self, func_index: c_int, n: u8) -> Option<&CStr>
Set the value of a closure’s upvalue and return its name.
Returns None (and pops nothing) when the index n is greater than the
number of upvalues.
This function assigns the value on the top of the stack to the upvalue. It also pops the value from the stack.
Sourcepub unsafe fn upvalue_id(&self, func_index: c_int, n: u8) -> *mut c_void
pub unsafe fn upvalue_id(&self, func_index: c_int, n: u8) -> *mut c_void
Return a unique identifier for the upvalue numbered n from the closure
at index func_index.
These unique identifiers allow a program to check whether different closures share upvalues. Lua closures that share an upvalue (that is, that access a same external local variable) will return identical ids for those upvalue indices.
§Safety
The returned pointer may only be used for comparisons.
Sourcepub fn upvalue_join(
&self,
func_into_index: i32,
n_into: u8,
func_from_index: i32,
n_from: u8,
)
pub fn upvalue_join( &self, func_into_index: i32, n_into: u8, func_from_index: i32, n_from: u8, )
Make the
n_into-th upvalue of the Lua closure at index func_into_index
refer to the
n_from-th upvalue of the Lua closure at index func_from_index.
Sourcepub fn new_buffer(&self) -> Buffer<'_>
pub fn new_buffer(&self) -> Buffer<'_>
Examples found in repository?
11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub fn arg_error(&self, arg: c_int, extra_message: &CStr) -> !
pub fn arg_error(&self, arg: c_int, extra_message: &CStr) -> !
Raise an error reporting a problem with argument arg of the C function
that called it, using a standard message that includes extra_message
as a comment:
bad argument #<argument> to '<function name>' (<message>)
This function never returns.
Sourcepub fn check_integer(&self, arg: c_int) -> Integer
pub fn check_integer(&self, arg: c_int) -> Integer
Sourcepub fn check_c_chars(&self, arg: c_int) -> &[c_char]
pub fn check_c_chars(&self, arg: c_int) -> &[c_char]
Sourcepub fn check_string(&self, arg: c_int) -> &[u8]
pub fn check_string(&self, arg: c_int) -> &[u8]
Works the same as Thread::check_c_chars, however it returns a slice
of u8s instead of c_chars.
§Errors
The underlying Lua state may raise an error if the
argument arg isn’t a string.
Examples found in repository?
11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub fn check_number(&self, arg: c_int) -> Number
pub fn check_number(&self, arg: c_int) -> Number
Check whether the function argument arg is a number and return this
number converted to a Number.
§Errors
The underlying Lua state may raise an error if the
argument arg’s type is incorrect.
Examples found in repository?
4unsafe extern "C-unwind" fn l_hello(l: *mut LuaState) -> c_int {
5 // SAFETY: Caller ensures `l` is valid.
6 let lua = unsafe { LuaThread::from_ptr(l) };
7
8 let n = lua.check_number(1);
9
10 // SAFETY: Ditto.
11 lua.push_string("Hello, world!");
12 lua.push_number(n * core::f64::consts::PI as LuaNumber);
13
14 2
15}Sourcepub fn check_option<const N: usize>(
&self,
arg: c_int,
default: Option<&CStr>,
list: &AuxOptions<'_, N>,
) -> usize
pub fn check_option<const N: usize>( &self, arg: c_int, default: Option<&CStr>, list: &AuxOptions<'_, N>, ) -> usize
Check whether the function argument arg is a string, search for this
string in the option list list and return the index in the list where
the string was found.
If default is Some, the function uses it as a default value when
there is no argument arg or when this argument is nil.
This is a useful function for mapping strings to C enums. (The usual convention in Lua libraries is to use strings instead of numbers to select options.)
§Errors
The underlying Lua state may raise an error if the
argument arg is not a string or if the string cannot be found in list.
Sourcepub fn check_stack(&self, size: c_int, message: Option<&CStr>)
pub fn check_stack(&self, size: c_int, message: Option<&CStr>)
Sourcepub fn check_c_str(&self, arg: c_int) -> &CStr
pub fn check_c_str(&self, arg: c_int) -> &CStr
Sourcepub fn check_type(&self, arg: c_int, type_tag: Type)
pub fn check_type(&self, arg: c_int, type_tag: Type)
Sourcepub unsafe fn check_udata(
&self,
arg: c_int,
table_name: &CStr,
) -> NonNull<c_void>
pub unsafe fn check_udata( &self, arg: c_int, table_name: &CStr, ) -> NonNull<c_void>
Check whether the function argument arg is a userdata of the type
table_name (see also Thread::new_metatable) and return the
userdata’s memory-block address (see Thread::to_userdata).
§Errors
The underlying Lua state may raise an error if the
argument arg’s type is incorrect.
§Safety
The returned pointer must only be used while it’s valid.
While the metatable of userdata is protected from modification in the Lua standard library,
an unsound implementation of setting the metatable of an object in Lua could change a userdatum’s metatable
and make the check for the table_name metatable unsound.
Sourcepub fn check_version(&self)
pub fn check_version(&self)
Check whether the code making the call and the Lua library being called are using the same version of Lua and the same numeric types.
§Errors
The underlying Lua state may raise an error if the above requirements aren’t met.
Examples found in repository?
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}Sourcepub fn error_c_str(&self, message: &CStr) -> !
pub fn error_c_str(&self, message: &CStr) -> !
Raise an error.
This function adds the file name and the line number where the error
occurred at the beginning of message, if this information is available.
This function never returns.
Sourcepub fn exec_result(&self, status: c_int) -> c_int
pub fn exec_result(&self, status: c_int) -> c_int
Sourcepub fn file_result(&self, status: c_int, file_name: &CStr) -> c_int
pub fn file_result(&self, status: c_int, file_name: &CStr) -> c_int
Sourcepub fn get_meta_field(&self, obj_index: c_int, event: &CStr) -> Type
pub fn get_meta_field(&self, obj_index: c_int, event: &CStr) -> Type
Push onto the stack the field event from the metatable of the object
at index obj_index and return the type of the pushed value.
If the object does not have a metatable, or if the metatable does not
have this field, this function pushes nothing and returns Type::Nil.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn get_aux_metatable(&self, table_name: &CStr) -> Type
pub fn get_aux_metatable(&self, table_name: &CStr) -> Type
Push onto the stack the metatable associated with the name table_name
in the registry (see also Thread::new_metatable), or nil if there
is no metatable associated with that name, and return the type of the
pushed value.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn load_c_chars(&self, buffer: &[c_char], name: &CStr) -> Status
pub fn load_c_chars(&self, buffer: &[c_char], name: &CStr) -> Status
Load a buffer as a Lua chunk.
This function works like Thread::load_string.
Sourcepub fn load_string(&self, buffer: impl AsRef<[u8]>, name: &CStr) -> Status
pub fn load_string(&self, buffer: impl AsRef<[u8]>, name: &CStr) -> Status
Load a buffer as a Lua chunk.
This function uses Thread::load to load the chunk in the buffer
pointed to by buffer, and will return the same results as that
function.
name is the chunk name, used for debug information and error messages.
Examples found in repository?
63fn main() {
64 let mut lua = Lua::new();
65 lua.run_managed(|mut mg| mg.open_libs());
66
67 if !lua.load_string(PRINT_CODE.as_bytes(), PRINT_CODE_LUA_NAME).is_ok() {
68 panic!("couldn't load Lua chunk");
69 }
70
71 lua.push(4 as LuaInteger);
72 lua.push(3.1 as LuaNumber);
73 lua.push("how");
74
75 if !lua.run_managed(|mut mg| {
76 mg.restart_gc();
77 unsafe { mg.pcall(3, 0, 0) }
78 }).is_ok() {
79 let error_bytes = lua.to_string(-1);
80 panic!(
81 "error while running Lua chunk: {}",
82 error_bytes.map(String::from_utf8_lossy)
83 .unwrap_or(std::borrow::Cow::Borrowed("<no message>"))
84 );
85 }
86}More examples
6unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
7 let lua = unsafe { LuaThread::from_ptr_mut(l) };
8 lua.run_managed(move |mut mg| mg.open_libs());
9
10 let is_ok = lua.load_string(
11 r#"print("Hello, world!")"#,
12 c"=<embedded>"
13 ).is_ok();
14 if !is_ok {
15 let error = {
16 lua.to_string(-1)
17 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
18 .unwrap_or("<message is not UTF-8>")
19 };
20 eprintln!("couldn't load example Lua code:\n\t{error}");
21 lua.push_boolean(false);
22 return 1
23 }
24
25 let is_ok = lua.run_managed(move |mut mg| unsafe { mg.pcall(0, 0, 0).is_ok() });
26 if !is_ok {
27 let error = {
28 lua.to_string(-1)
29 .and_then(move |bytes| core::str::from_utf8(bytes).ok())
30 .unwrap_or("<message is not UTF-8>")
31 };
32 eprintln!("couldn't run example Lua code:\n\t{error}");
33 lua.push_boolean(false);
34 return 1
35 }
36
37 lua.push_boolean(true);
38 1
39}Sourcepub fn load_file(&self, file_name: &CStr) -> Status
pub fn load_file(&self, file_name: &CStr) -> Status
Load a file as a Lua chunk.
This function uses Thread::load to load the chunk in the file
file_name.
The first line in the file is ignored if it starts with a #.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}Sourcepub fn load_stdin(&self) -> Status
pub fn load_stdin(&self) -> Status
Load a Lua chunk from the standard input.
This function uses Thread::load to load the chunk.
The first line in the file is ignored if it starts with a #.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
55unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
56 let lua = unsafe { LuaThread::from_ptr_mut(l) };
57
58 lua.check_version();
59 lua.run_managed(|mut mg| mg.open_libs());
60
61 lua.push_c_function(l_err_handler);
62 let base = lua.top();
63
64 let mut arguments = args().skip(1);
65 let load_status = if let Some(mut file_name) = arguments.next() {
66 lua.load_file(unsafe {
67 file_name.push('\0');
68 CStr::from_bytes_until_nul(file_name.as_bytes()).unwrap_unchecked()
69 })
70 } else {
71 lua.load_stdin()
72 };
73
74 if !report(lua, load_status) {
75 return 0
76 }
77
78 let mut arg_count: c_uint = 0;
79 for arg in arguments {
80 lua.push_string(arg.as_bytes());
81 arg_count += 1;
82 }
83
84 let run_status = lua.run_managed(|mut mg| {
85 mg.restart_gc();
86 let run_status = unsafe { mg.pcall(arg_count, 0, base) };
87 mg.stop_gc();
88 run_status
89 });
90 if !report(lua, run_status) {
91 return 0
92 }
93
94 lua.push_boolean(true);
95 1
96}Sourcepub fn load_c_str(&self, code: &CStr) -> Status
pub fn load_c_str(&self, code: &CStr) -> Status
Load a string as a Lua chunk.
This function uses Thread::load to load code.
Sourcepub fn new_lib<const N: usize>(&self, library: &Library<'_, N>)
pub fn new_lib<const N: usize>(&self, library: &Library<'_, N>)
Create a new table and register there the functions in the list library.
Unlike this function’s C counterpart, this will not call
Thread::check_version.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
More examples
Sourcepub fn new_lib_table<const N: usize>(&self, library: &Library<'_, N>)
pub fn new_lib_table<const N: usize>(&self, library: &Library<'_, N>)
Create a new table with a size optimized to store all entries in
library, but does not actually store them.
This function is intended to be used in conjunction with
Thread::set_funcs.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn new_metatable(&self, table_name: &CStr) -> bool
pub fn new_metatable(&self, table_name: &CStr) -> bool
If the registry already doesn’t have the key table_name, create a new
table to be used as a metatable for userdata and return true.
Otherwise, return false.
In both cases, the function pushes onto the stack the final value
associated with table_name in the registry.
The function adds to this new table the pair __name = table_name,
adds to the registry the pair [table_name] = table, and returns true.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn opt_integer(&self, arg: c_int, default: Integer) -> Integer
pub fn opt_integer(&self, arg: c_int, default: Integer) -> Integer
Sourcepub fn opt_c_chars<'l>(&'l self, arg: c_int, default: &'l CStr) -> &'l [c_char]
pub fn opt_c_chars<'l>(&'l self, arg: c_int, default: &'l CStr) -> &'l [c_char]
If the function argument arg is a string, return this string, or
return default.
This function works like Thread::opt_string.
§Errors
The underlying Lua state may raise an error if the
argument arg isn’t a string, isn’t a nil and not absent.
Sourcepub fn opt_c_str<'l>(&'l self, arg: c_int, default: &'l CStr) -> &'l CStr
pub fn opt_c_str<'l>(&'l self, arg: c_int, default: &'l CStr) -> &'l CStr
If the function argument arg is a string, return this string, or
return default.
This function works like Thread::opt_string.
§Errors
The underlying Lua state may raise an error if the
argument arg isn’t a string, isn’t a nil and not absent.
Sourcepub fn opt_string<'l>(&'l self, arg: c_int, default: &'l [u8]) -> &'l [u8]
pub fn opt_string<'l>(&'l self, arg: c_int, default: &'l [u8]) -> &'l [u8]
If the function argument arg is a string, return this string, or
return default.
This function uses Thread::to_string to get its result, so all
conversions and caveats of that function apply here.
§Errors
The underlying Lua state may raise an error if the
argument arg isn’t a string, isn’t a nil and not absent.
Sourcepub fn opt_number(&self, arg: c_int, default: Number) -> Number
pub fn opt_number(&self, arg: c_int, default: Number) -> Number
Sourcepub fn push_fail(&self)
pub fn push_fail(&self)
Pushes the fail value onto the stack.
Examples found in repository?
39 fn push_into(&self, thread: &LuaThread) {
40 match self {
41 Self::Ok(t) => {
42 t.push_into(thread);
43 thread.push_nil()
44 }
45 Self::Err(e) => {
46 thread.push_fail();
47 e.push_into(thread)
48 }
49 }
50 }More examples
11unsafe extern "C-unwind" fn l_metadata(l: *mut LuaState) -> c_int {
12 let lua = unsafe { LuaThread::from_ptr_mut(l) };
13 let path = lua.check_string(1);
14
15 let meta = match metadata(String::from_utf8_lossy(path).into_owned()) {
16 Ok(meta) => meta,
17 Err(error) => {
18 lua.push_fail();
19 let mut buf = lua.new_buffer();
20 let _ = write!(buf, "{error}");
21 return 2
22 }
23 };
24
25 lua.run_managed(|mut mg| {
26 mg.create_table(0, 1);
27
28 let file_type = meta.file_type();
29 mg.push_string(if file_type.is_file() {
30 "file"
31 } else if file_type.is_dir() {
32 "directory"
33 } else if file_type.is_symlink() {
34 "symlink"
35 } else {
36 "other"
37 }.as_bytes());
38 mg.set_field(-2, c"type");
39
40 mg.push_integer(meta.len() as _);
41 mg.set_field(-2, c"len");
42
43 if let Ok(time) = meta.modified() {
44 if let Ok(time) = time.duration_since(SystemTime::UNIX_EPOCH) {
45 mg.push_number(time.as_secs_f64());
46 mg.set_field(-2, c"modified");
47 }
48 }
49 });
50
51 1
52}Sourcepub fn create_ref(&self, store_index: c_int) -> c_int
pub fn create_ref(&self, store_index: c_int) -> c_int
Create and return a reference, in the table at index store_index, for
the object on the top of the stack (popping the object).
A reference is a unique integer key.
As long as you do not manually add integer keys into the table
store_index, this function ensures the uniqueness of the key it
returns.
You can retrieve an object referred by the reference ref_idx by
calling thread.raw_get_i(store_index, ref_idx).
See also Thread::destroy_ref, which frees a reference.
If the object on the top of the stack is nil, this returns the constant
REF_NIL.
The constant NO_REF is guaranteed to be different from any reference
returned.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn set_funcs<const N: usize>(
&self,
library: &Library<'_, N>,
n_upvalues: u8,
)
pub fn set_funcs<const N: usize>( &self, library: &Library<'_, N>, n_upvalues: u8, )
Registers all functions in the list library into the table on the top
of the stack (below optional upvalues).
When n_upvalues is not zero, all functions are created with
n_upvalues upvalues, initialized with copies of the values previously
pushed on the stack on top of the library table.
These values are popped from the stack after the registration.
See also Library.
A value with a None value represents a placeholder, which is filled
with false.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn set_aux_metatable(&self, table_name: &CStr)
pub fn set_aux_metatable(&self, table_name: &CStr)
Set the metatable of the object on the top of the stack as the metatable
associated with name table_name in the registry.
See also Thread::new_metatable.
Sourcepub unsafe fn test_udata(
&self,
arg: c_int,
table_name: &CStr,
) -> Option<NonNull<c_void>>
pub unsafe fn test_udata( &self, arg: c_int, table_name: &CStr, ) -> Option<NonNull<c_void>>
This function works like Thread::check_udata, except that, when the
test fails, it returns None instead of raising an error.
§Safety
The returned pointer must only be used while it’s valid.
While the metatable of userdata is protected from modification in the Lua standard library,
an unsound implementation of setting the metatable of an object in Lua could change a userdatum’s metatable
and make the check for the table_name metatable unsound.
Sourcepub fn traceback(&self, of: &Self, message: Option<&CStr>, level: c_int)
pub fn traceback(&self, of: &Self, message: Option<&CStr>, level: c_int)
Create and push a traceback of the stack of thread of.
If message is Some, it is appended at the beginning of the traceback.
level tells at which level to start the traceback.
§Errors
The underlying Lua state may raise a memory error.
Examples found in repository?
34unsafe extern "C-unwind" fn l_err_handler(l: *mut LuaState) -> c_int {
35 let lua = unsafe { LuaThread::from_ptr_mut(l) };
36
37 if let Some(msg) = lua.to_c_str(1) {
38 lua.traceback(lua, Some(msg), 1);
39 return 1
40 }
41
42 let ok = lua.run_managed(|mut mg| unsafe {
43 mg.call_metamethod(1, c"__tostring")
44 });
45
46 if ok && lua.type_of(-1) == LuaType::String {
47 return 1
48 }
49
50 unsafe { lua_push_fmt_string!(lua, c"(error object is a %s value)", lua.type_name_of(1)) };
51
52 1
53}Sourcepub fn traceback_self(&self, message: Option<&CStr>, level: c_int)
pub fn traceback_self(&self, message: Option<&CStr>, level: c_int)
Create and push a traceback of the stack of this thread to its own stack.
This function works like Thread::traceback.
§Errors
The underlying Lua state may raise a memory error.
Sourcepub fn type_error(&self, arg: c_int, type_name: &CStr) -> !
pub fn type_error(&self, arg: c_int, type_name: &CStr) -> !
Raise a type error for the argument arg of the C function that called
it, using a standard message;
type_name is a “name” for the expected type.
This function never returns.
Sourcepub fn type_name_of(&self, index: c_int) -> &CStr
pub fn type_name_of(&self, index: c_int) -> &CStr
Return the name of the type of the value at the given index.
Examples found in repository?
34unsafe extern "C-unwind" fn l_err_handler(l: *mut LuaState) -> c_int {
35 let lua = unsafe { LuaThread::from_ptr_mut(l) };
36
37 if let Some(msg) = lua.to_c_str(1) {
38 lua.traceback(lua, Some(msg), 1);
39 return 1
40 }
41
42 let ok = lua.run_managed(|mut mg| unsafe {
43 mg.call_metamethod(1, c"__tostring")
44 });
45
46 if ok && lua.type_of(-1) == LuaType::String {
47 return 1
48 }
49
50 unsafe { lua_push_fmt_string!(lua, c"(error object is a %s value)", lua.type_name_of(1)) };
51
52 1
53}Sourcepub fn destroy_ref(&self, store_index: c_int, ref_idx: c_int)
pub fn destroy_ref(&self, store_index: c_int, ref_idx: c_int)
Release the reference ref_idx from the table at index store_index.
If ref_idx is NO_REF or REF_NIL, this function does nothing.
The entry is removed from the table, so that the referred object can be
collected.
The reference ref_idx is also freed to be used again.
See also Thread::create_ref.
Sourcepub fn where_string(&self, level: c_int)
pub fn where_string(&self, level: c_int)
Push onto the stack a string identifying the current position of the
control at level level in the call stack.
Typically, this string has the following format:
chunkname:currentline:
Level 0 is the running function, level 1 is the function that called
the running function, etc.
This function is used to build a prefix for error messages.
§Errors
The underlying Lua state may raise a memory error.