low_luajit/lua/state.rs
1use core::ptr;
2
3use crate::ffi::{self, lua_State};
4
5/// Opaque container of the state of a Lua interpreter and entry point to the LuaJIT C API.
6///
7/// See the [top-level documentation](index.html) for details on how to access `LuaState`.
8///
9/// Most functions assume you have a general understanding of the virtual stack the Lua interpreter uses.
10/// If not, refer to [§3.1](https://www.lua.org/manual/5.1/manual.html#3.1) and [§3.2](https://www.lua.org/manual/5.1/manual.html#3.1).
11///
12/// A `LuaState` (and its wrapped pointer) should always be valid (unless unsafe constructors are used incorrectly) and will be treated as such.
13///
14/// *(Most of the methods' documentation below, and a few other places,
15/// has been written using the [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/manual.html) as reference:
16/// Copyright © 2006–2012 Lua.org, PUC-Rio. Licensed under the [MIT license](https://www.lua.org/license.html).*)
17#[repr(transparent)]
18#[derive(Debug, PartialEq, Eq)]
19pub struct LuaState(pub(super) *mut ffi::lua_State);
20
21/// State handling functions.
22impl LuaState {
23 /* Not yet...
24 /// Creates a new valid and independent Lua state.
25 ///
26 /// This state will use the standard C `realloc` function as its allocator.
27 ///
28 /// # Safety
29 ///
30 /// While there is nothing inherently unsafe about creating a new `LuaState`,
31 /// using the state without a protected environment could end badly in case a Lua error is triggered:
32 /// at best, Rust simply aborts abruptly...but I've had segmentation faults happen sometimes too.
33 #[inline]
34 pub unsafe fn new_unchecked() -> Self {
35 let ptr = unsafe { luaL_newstate() };
36 assert!(!ptr.is_null(), "cannot create new Lua state: memory allocation error");
37 Self(ptr)
38 }*/
39
40 /// Wraps a pre-existing raw [`lua_State`] pointer.
41 ///
42 /// # Safety
43 ///
44 /// `ptr` **must** be a valid pointer of an already existing state, as all other methods will assume it to be so.
45 ///
46 /// Additionally, there must not be an existing accessible `LuaState` that is already using this pointer.
47 #[must_use]
48 pub const unsafe fn from_ptr(ptr: *mut lua_State) -> Self {
49 Self(ptr)
50 }
51
52 /// Returns the underlying raw [`lua_State`] pointer.
53 /// This can be used to pass the `LuaState` to raw [`ffi`] functions.
54 ///
55 /// The caller must ensure that the `LuaState` outlives the pointer this function returns, or else it will end up dangling.
56 ///
57 /// The returned pointer should also not be passed to functions that might invalidate the `LuaState` (like [`lua_close`]).
58 ///
59 /// [`lua_close`]: ./ffi/fn.lua_close.html
60 #[must_use]
61 pub const fn as_ptr(&self) -> *mut lua_State {
62 self.0
63 }
64
65 /// Grants temporary mutable access to the [`LuaState`] from an immutable reference.
66 /// This function should be used seldomly.
67 ///
68 /// # Safety
69 ///
70 /// `f` must not pop any pre-existing element and any element pushed onto the stack by `f` should be popped before the function ends.
71 ///
72 /// *(Not popping all pushed elements currently only constitutes a logic error,
73 /// but this may change in the future and should not be relied upon unless necessary.)*
74 pub unsafe fn access_mut<T>(&self, f: impl FnOnce(&mut Self) -> T) -> T {
75 #[cfg(debug_assertions)]
76 let top = self.get_top();
77 // SAFETY: self.0 is always valid and the caller must uphold the safety conditions.
78 let mut lua = unsafe { Self::from_ptr(self.0) };
79 let result = f(&mut lua);
80
81 #[cfg(debug_assertions)]
82 debug_assert!(top == self.get_top(), "mutably accessed the Lua state as the stack held {top} elements, but left it with {} elements instead", self.get_top());
83 result
84 }
85
86 /// Destroys all objects and frees all dynamic memory of the state.
87 ///
88 /// # Safety
89 ///
90 /// Can only be called if this `LuaState` is not being used anywhere else.
91 ///
92 /// If your crate is a Lua module, this function must *not* return back to the Lua interpreter (as it would no longer exist).
93 #[inline]
94 pub unsafe fn close(self) {
95 // SAFETY: self.0 is always valid and the caller must make sure that the LuaState is not used anywhere else.
96 unsafe { ffi::lua_close(self.0); }
97 }
98
99 /// Returns a reference to a number that represents the version of Lua.
100 ///
101 /// For LuaJIT, this should always returns `501` (which represents 5.1, the Lua version LuaJIT is based on).
102 #[inline]
103 pub fn version() -> &'static f64 {
104 // SAFETY: lua_version doesn't actually use the pointer given to it and always returns a valid pointer to a static f64.
105 unsafe { &*ffi::lua_version(ptr::null_mut()) }
106 }
107}