Skip to main content

low_luajit/lua/
debug.rs

1use core::{ffi::CStr, mem::{self, MaybeUninit}, ptr};
2use crate::{LuaState, SafeFn, ffi::{self, LUA_IDSIZE, lua_Debug, lua_Hook}, map_ptr};
3
4#[cfg(doc)]
5use crate::CFunction;
6
7/// Debugging function that is called by specified [`HookEvent`]s.
8///
9/// See [`LuaState::set_hook`] for more information on how to enable an `Hook`.
10/// There can only be one `Hook` enabled at a time.
11///
12/// When called, `info` can be used to retrieve the [`HookEvent`] that called the hook (see [`DebugInfo::event`]).
13///
14/// If [`HookEvent::Line`] is the event that called the `Hook`, [`DebugInfo::current_line`] will also be set.
15///
16/// To get more information about the function that was running at the time,
17/// [`LuaState::get_info`] can be called using `info` without needing to specify a function using [`LuaState::get_stack`].
18///
19/// While the current `Hook` is running, it cannot be called again.
20/// Which means it is possible to call other functions from within the hook itself without issues.
21///
22/// Just like [`CFunction`], this type is technically a *subset* of [`lua_Hook`], as it only allows safe functions.
23/// Different methods will use either [`lua_Hook`] or `Hook` based on if they work with only safe functions or not.
24pub type Hook = extern "C-unwind" fn(lua: LuaState, info: &mut DebugInfo);
25
26impl SafeFn for Hook {
27	type RawFn = lua_Hook;
28
29	#[inline]
30	unsafe fn from_raw(raw: lua_Hook) -> Self {
31		// SAFETY: lua_Hook and Hook are effectively the same.
32		unsafe { mem::transmute(raw) }
33	}
34
35	#[inline]
36	fn to_raw(self) -> lua_Hook {
37		// SAFETY: Hook and lua_Hook are effectively the same.
38		unsafe { mem::transmute(self) }
39	}
40}
41
42/// All possible event types that can call the current [`Hook`].
43#[repr(i32)]
44#[derive(Debug, Clone, Copy)]
45pub enum HookEvent {
46	/// Calls the current [`Hook`] whenever a function is called, just after Lua enters the function but before it receives its arguments.
47	Call = ffi::LUA_HOOKCALL,
48
49	/// Calls the current [`Hook`] whenever a called function returns, just before Lua leaves the function.
50	///
51	/// The values being returned by the returning function cannot be accessed.
52	Return = ffi::LUA_HOOKRET,
53
54	/// Calls the current [`Hook`] whenever a new line of code is executed or when Lua jumps back to a previous (or the same) line.
55	///
56	/// This event only happens for Lua functions (not [`CFunction`]s).
57	Line = ffi::LUA_HOOKLINE,
58
59	/// Calls the current [`Hook`] every time after Lua executes a specified amount of instructions (see [`LuaState::set_hook`]).
60	///
61	/// This event only happens for Lua functions (not [`CFunction`]s).
62	Count = ffi::LUA_HOOKCOUNT,
63}
64
65impl HookEvent {
66	/// [`HookEvent::Call`]'s mask value.
67	///
68	/// See [`LuaState::set_hook`] for more information.
69	pub const MASK_CALL: i32 = ffi::LUA_MASKCALL;
70
71	/// [`HookEvent::Return`]'s mask value.
72	///
73	/// See [`LuaState::set_hook`] for more information.
74	pub const MASK_RETURN: i32 = ffi::LUA_MASKRET;
75
76	/// [`HookEvent::Line`]'s mask value.
77	///
78	/// See [`LuaState::set_hook`] for more information.
79	pub const MASK_LINE: i32 = ffi::LUA_MASKLINE;
80
81	/// [`HookEvent::Count`]'s mask value.
82	///
83	/// See [`LuaState::set_hook`] for more information.
84	pub const MASK_COUNT: i32 = ffi::LUA_MASKCOUNT;
85
86	/// Returns this `HookEvent`'s mask value.
87	///
88	/// See [`LuaState::set_hook`] for more information.
89	#[inline]
90	#[must_use]
91	pub const fn as_mask(self) -> i32 {
92		1 << self as i32
93	}
94}
95
96/// Activation record related to a specified active function.
97///
98/// All internal fields of this record may be unset if not requested,
99/// the methods describe how to request the field they return.
100///
101/// `DebugInfo`s can be directly created and used (see [`DebugInfo::new`]) or are passed as arguments to hooks (see [`Hook`]).
102///
103/// Requesting information related to different functions using the same `DebugInfo`
104/// will result in the activation record containing information related to both functions simultaneously...which could be confusing.
105/// *(Unless the requested information is the same both times, in which case all the info is just overwritten.)*
106#[repr(transparent)]
107#[derive(Debug, Clone)]
108pub struct DebugInfo(lua_Debug);
109
110/// Extracts the possibly uninitialized field only if the `DebugInfo::IS_FULLY_INIT` flag is toggled on.
111///
112/// Otherwise it makes the function return `None`.
113macro_rules! get_maybe_uninit_field {
114	($self:ident.$zero:literal.$field:ident) => {
115		if $self.is_fully_init() {
116			// SAFETY: IS_FULLY_INIT should only be toggled on when all fields are initialized.
117			unsafe { $self.0.$field.assume_init() }
118		} else {
119			return None;
120		}
121	};
122	(&raw $self:ident.$zero:literal.$field:ident) => {
123		if $self.is_fully_init() { $self.0.$field.as_ptr() } else { return None; }
124	};
125}
126
127impl DebugInfo {
128	/// Creates a new `DebugInfo`.
129	///
130	/// All the internal fields of the returned activation record will be unset, see [`LuaState::get_info`] to request information.
131	#[inline]
132	#[must_use]
133	pub const fn new() -> Self {
134		Self(lua_Debug {
135			event: -1 | Self::IS_FULLY_INIT,
136			name: MaybeUninit::new(ptr::null()),
137			namewhat: MaybeUninit::new(ptr::null()),
138			what: MaybeUninit::new(ptr::null()),
139			source: MaybeUninit::new(ptr::null()),
140			currentline: -1,
141			nups: MaybeUninit::new(-1),
142			linedefined: MaybeUninit::new(-1),
143			lastlinedefined: MaybeUninit::new(-1),
144			short_src: MaybeUninit::new([1; ffi::LUA_IDSIZE]),
145			i_ci: 0,
146		})
147	}
148
149	/// Wraps a pre-existing raw [`lua_Debug`].
150	///
151	/// # Safety
152	///
153	/// If all `MaybeUninit` fields are initialized:
154	/// - `name`, `namewhat`, `what`, and `source` must either be null or point to valid nul-terminated strings.
155	/// - `event` must either be `-1` or the numerical value of any [`HookEvent`] value bit or'd with `1 << 31`.
156	///
157	/// If all `MaybeUninit` fields are uninitialized:
158	/// - `event` must be just the numerical value of any [`HookEvent`] value.
159	///
160	/// A non-modified [`lua_Debug`] obtained from [`DebugInfo::into_raw`] should always be safe to use.
161	///
162	/// If the private field is somehow accessed, it should preferably be kept at `0` or otherwise any value Lua might set it to.
163	#[inline]
164	#[must_use]
165	pub const unsafe fn from_raw(raw: lua_Debug) -> Self {
166		Self(raw)
167	}
168
169	/// Returns the wrapped [`lua_Debug`].
170	///
171	/// There are no guarantees on the raw fields of the returned [`lua_Debug`]:
172	/// some fields may have unexpected values and the `MaybeUninit` fields may not be initialized.
173	///
174	/// The raw [`lua_Debug`] can be safely converted back into a `DebugInfo` using [`DebugInfo::from_raw`], as long as it is not modified.
175	#[inline]
176	#[must_use]
177	pub const fn into_raw(self) -> lua_Debug {
178		self.0
179	}
180
181	/// Returns a pointer to the wrapped [`lua_Debug`].
182	/// This can be used to pass this `DebugInfo` to raw [`ffi`] functions.
183	///
184	/// The caller must ensure that the `DebugInfo` outlives the pointer this function returns, or else it will end up dangling.
185	#[inline]
186	#[must_use]
187	pub const fn as_ptr(&self) -> *const lua_Debug {
188		&raw const self.0
189	}
190
191	/// Returns a mutable pointer to the wrapped [`lua_Debug`].
192	/// This can be used to pass this `DebugInfo` to raw [`ffi`] functions.
193	///
194	/// The caller must ensure that the `DebugInfo` outlives the pointer this function returns, or else it will end up dangling.
195	#[inline]
196	#[must_use]
197	pub const fn as_mut_ptr(&mut self) -> *mut lua_Debug {
198		&raw mut self.0
199	}
200
201	/// Internal hack to keep `DebugInfo` safe to use:
202	/// when received from an [`Hook`], most of the fields are left uninitialized.
203	///
204	/// Any method that may read a potentially uninitialized field will first check if `event` contains this bit flag:
205	/// if not, the field will not be read and `None` will be returned.
206	///
207	/// If [`LuaState::get_info`] is called using a `DebugInfo` that is not masked as fully initialized,
208	/// the potentially uninitialized fields will be set to their default value and the `DebugInfo` will be marked as initialized.
209	///
210	/// The advantage of this solution is that `DebugInfo`s created from within Rust continue to function almost completely normally,
211	/// while `DebugInfo`s received from an [`Hook`] can be used safely and are fully initialized only when actually needed.
212	///
213	/// The disadvantage is that the `event` field is used for more than it was meant to and requires this bit flag to be removed whenever read,
214	/// which is an acceptable trade-off in my opinion.
215	const IS_FULLY_INIT: i32 = 1 << 31;
216
217	#[must_use]
218	const fn is_fully_init(&self) -> bool {
219		self.0.event & Self::IS_FULLY_INIT != 0
220	}
221
222	/// Returns the literal source of the specified function if said function was loaded via a string.
223	/// Otherwise, it returns the chunk name, which is usually `'@'` followed by the file path or `"=[C]"` (but could be anything).
224	///
225	/// This field will only be set if the `'S'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
226	#[inline]
227	#[must_use]
228	pub const fn source(&self) -> Option<&CStr> {
229		let source = get_maybe_uninit_field!(self.0.source);
230		// SAFETY: self.0.source should always be a valid nul-terminated string pointer when not null.
231		map_ptr!(source, unsafe { CStr::from_ptr(source) })
232	}
233
234	/// Returns a "printable" version of [`DebugInfo::source`], intended to be used in error messages (which Lua does).
235	///
236	/// The returned string is never longer than 60 characters.
237	///
238	/// This field will only be set if the `'S'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
239	#[inline]
240	#[must_use]
241	pub const fn short_source(&self) -> Option<&CStr> {
242		let short_source = get_maybe_uninit_field!(&raw self.0.short_src);
243		// SAFETY: self.0.short_src is initialized and casting from [c_char] to [u8] is safe since they're both just 1 byte.
244		match CStr::from_bytes_until_nul(unsafe { &*short_source.cast::<[u8; ffi::LUA_IDSIZE]>() }) {
245			Ok(short_src) => Some(short_src),
246			Err(_) => None,
247		}
248	}
249
250	/// Returns the line number where the definition of the specified Lua function starts.
251	/// [`CFunction`]s return `None` instead.
252	///
253	/// This field will only be set if the `'S'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
254	#[inline]
255	#[must_use]
256	pub const fn line_defined(&self) -> Option<i32> {
257		match get_maybe_uninit_field!(self.0.linedefined) {
258			-1 => None,
259			linedefined => Some(linedefined),
260		}
261	}
262
263	/// Returns the line number where the definition of the specified Lua function ends.
264	/// [`CFunction`]s return `None` instead.
265	///
266	/// This field will only be set if the `'S'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
267	#[inline]
268	#[must_use]
269	pub const fn last_line_defined(&self) -> Option<i32> {
270		match get_maybe_uninit_field!(self.0.lastlinedefined) {
271			-1 => None,
272			lastlinedefined => Some(lastlinedefined),
273		}
274	}
275
276	/// Returns what the specified function is:
277	/// - `"Lua"` for Lua functions.
278	/// - `"C"` for [`CFunction`]s.
279	/// - `"main"` if it's the main part of a chunk.
280	///
281	/// This field will only be set if the `'S'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
282	#[inline]
283	#[must_use]
284	pub const fn what(&self) -> Option<&CStr> {
285		let what = get_maybe_uninit_field!(self.0.what);
286		// SAFETY: self.0.what should always be a valid nul-terminated string pointer when not null.
287		map_ptr!(what, unsafe { CStr::from_ptr(what) })
288	}
289
290	/// Returns, if known, the current line where the specified function is executing.
291	/// `None` is returned if the current line is not known.
292	///
293	/// This field will only be set if the `'l'` selector is used (see [`LuaState::get_info`]) or within [`Hook`]s called by [`HookEvent::Line`]
294	/// (see [`Hook`]), and will always be `None` otherwise.
295	#[inline]
296	#[must_use]
297	pub const fn current_line(&self) -> Option<i32> {
298		match self.0.currentline {
299			-1 => None,
300			currentline => Some(currentline),
301		}
302	}
303
304	/// Returns a reasonable name for the specified function based on how it was called, or `None` if no suitable name could be found.
305	///
306	/// This field will only be set if the `'n'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
307	#[inline]
308	#[must_use]
309	pub const fn name(&self) -> Option<&CStr> {
310		let name = get_maybe_uninit_field!(self.0.name);
311		// SAFETY: self.0.name should always be a valid nul-terminated string pointer when not null.
312		map_ptr!(name, unsafe { CStr::from_ptr(name) })
313	}
314
315	/// Returns an explenation of how [`DebugInfo::name`] is found.
316	///
317	/// Possible returned values are:
318	/// - `"global"`.
319	/// - `"local"`.
320	/// - `"method"`.
321	/// - `"field"`.
322	/// - `"upvalue"`.
323	/// - `"metamethod"`.
324	/// - `""`. *(Returned when no other option applies or no suitable name was found.)*
325	///
326	/// This field will only be set if the `'n'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
327	#[inline]
328	#[must_use]
329	pub const fn name_what(&self) -> Option<&CStr> {
330		let namewhat = get_maybe_uninit_field!(self.0.namewhat);
331		// SAFETY: self.0.namewhat should always be a valid nul-terminated string pointer when not null.
332		map_ptr!(namewhat, unsafe { CStr::from_ptr(namewhat) })
333	}
334
335	/// Returns the number of upvalues of the specified function.
336	///
337	/// This field will only be set if the `'u'` selector is used (see [`LuaState::get_info`]), and will always be `None` otherwise.
338	#[inline]
339	#[must_use]
340	#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
341	pub const fn n_upvalues(&self) -> Option<u8> {
342		match get_maybe_uninit_field!(self.0.nups) {
343			-1 => None,
344			nups => Some(nups as u8),
345		}
346	}
347
348	/// Returns the [`HookEvent`] that called the current [`Hook`].
349	///
350	/// This field will only be set if this `DebugInfo` comes from the [`Hook`]'s arguments (see [`Hook`]), and will always be `None` otherwise.
351	#[inline]
352	#[must_use]
353	pub const fn event(&self) -> Option<HookEvent> {
354		match self.0.event {
355			-1 => None, // SAFETY: self.0.event (without the IS_FULLY_INIT flag) should always be a valid HookEvent.
356			event => Some(unsafe { mem::transmute::<i32, HookEvent>(event & !Self::IS_FULLY_INIT) })
357		}
358	}
359}
360
361impl Default for DebugInfo {
362	#[inline]
363	fn default() -> Self {
364		Self::new()
365	}
366}
367
368/// Debug interface functions.
369///
370/// See [ยง3.8](https://www.lua.org/manual/5.1/manual.html#3.8) for more information on the Debug interface.
371///
372/// *[See also the `DebugInfo` struct](struct.DebugInfo.html)*.
373impl LuaState {
374	/// Requests information about a specified function. The retrieved information will be stored in `info`.
375	///
376	/// There are three ways to specify a function:
377	/// - From the interpreter runtime stack by using [`LuaState::get_stack`].
378	/// - From the top element by adding `'>'` at the start of `what` (the element will be popped).
379	/// - Pre-specified when [`DebugInfo`] is received from an [`Hook`]'s arguments (see [`Hook`]).
380	///
381	/// The type of information requested is based on which "selectors" (characters) `what` contains:
382	/// - `'n'` will set [`DebugInfo::name`] and [`DebugInfo::name_what`].
383	/// - `'S'` will set [`DebugInfo::source`], [`DebugInfo::short_source`], [`DebugInfo::line_defined`],
384	///   [`DebugInfo::last_line_defined`], and [`DebugInfo::what`].
385	/// - `'l'` will set [`DebugInfo::current_line`].
386	/// - `'u'` will set [`DebugInfo::n_upvalues`].
387	/// - `'f'` pushes onto the stack the specified function itself.
388	/// - `'L'` pushes onto the stack a table whose indices are the number of valid lines (with associated code) of the specified function.
389	///
390	/// *(The selectors are executed based on their order in `what`.)*
391	///
392	/// If an invalid character is present in `what`, or `'>'` is used and the top elemenet is not a function,
393	/// this function will end early and return `false`. `true` is returned otherwise.
394	///
395	/// # Panics
396	///
397	/// Panics if none of the three ways of specifying a function are attempted.
398	#[inline]
399	pub fn get_info(&mut self, what: &CStr, info: &mut DebugInfo) -> bool {
400		// SAFETY: c_char can be casted as u8 (they're both 1 byte) and CStrs should always have at least 1 character (the nul terminator).
401		assert!(info.0.i_ci != 0 || unsafe { *what.as_ptr().cast::<u8>() == b'>' }, "tried to get debug information without specifying a function");
402
403		if !info.is_fully_init() {
404			// Initialize all MaybeUninit fields and mark the DebugInfo as fully initialized.
405			info.0.name.write(ptr::null());
406			info.0.namewhat.write(ptr::null());
407			info.0.what.write(ptr::null());
408			info.0.source.write(ptr::null());
409			info.0.nups.write(-1);
410			info.0.linedefined.write(-1);
411			info.0.lastlinedefined.write(-1);
412			info.0.short_src.write([1; LUA_IDSIZE]);
413			info.0.event |= DebugInfo::IS_FULLY_INIT;
414		}
415
416		// SAFETY: self.0, what, and info should always be valid and info either has a valid i_ci value or '>' is being used.
417		unsafe { ffi::lua_getinfo(self.0, what.as_ptr(), info.as_mut_ptr()) != 0 }
418	}
419
420	/// Prepare the given `info` to specify the function at the given `level`:
421	/// level `0` is the current running function, level `1` is the function that called the current running function, and so on.
422	///
423	/// If the given `level` is invalid, `info` is not prepared and the function returns `false`. `true` is returned otherwise.
424	///
425	/// This function is meant to be used alongside [`LuaState::get_info`] to get information about the specified function.
426	#[inline]
427	pub fn get_stack(&self, level: i32, info: &mut DebugInfo) -> bool {
428		// SAFETY: self.0 and info are always valid.
429		let success = unsafe { ffi::lua_getstack(self.0, level, info.as_mut_ptr()) != 0 };
430
431		if !success {
432			// Reset i_ci to keep it marked as invalid.
433			info.0.i_ci = 0;
434		}
435
436		success
437	}
438
439	/// Get information about a local variable of a specified function.
440	///
441	/// There are three ways to specify a function:
442	/// - From the interpreter runtime stack by using [`LuaState::get_stack`].
443	/// - From the top element by passing `None` for `info` (the element will *not* be popped).
444	/// - Pre-specified when [`DebugInfo`] is received from an [`Hook`]'s arguments (see [`Hook`]).
445	///
446	/// `n` selects which local to get, `1` being the first local and so on until the last local.
447	/// Negative values of `n` can be used to get vararg arguments.
448	///
449	/// When `info` is `Some`, this function will push to the stack the local's value and return the local's name.
450	/// Otherwise only the name is returned and nothing is pushed to the stack.
451	///
452	/// Invalid values of `n` or the top element not being a function (when `info` is `None`)
453	/// will result in the function returning `None` and pushing nothing to the stack.
454	///
455	/// If the returned name is enclosed in round brackets, the queried local is an internal variable.
456	///
457	/// # Panics
458	///
459	/// Panics if none of the three ways of specifying a function are attempted.
460	#[inline]
461	pub fn get_local(&mut self, info: Option<&DebugInfo>, n: i32) -> Option<&CStr> {
462		if let Some(info) = info {
463			assert!(info.0.i_ci != 0, "tried to get a local without specifying a function");
464		}
465
466		// SAFETY: self.0 and info's pointer are always valid, lua_getlocal accepts a null lua_Debug,
467		// and lua_getlocal returns valid nul-terminated string pointers when not null.
468		let local = unsafe { ffi::lua_getlocal(self.0, info.map_or(ptr::null(), DebugInfo::as_ptr), n) };
469		map_ptr!(local, unsafe { CStr::from_ptr(local) })
470	}
471
472	/// Sets the value of a local variable of a specified function to the value of the top element (which is popped),
473	/// returning the local's name.
474	///
475	/// There are *two* ways to specify a function:
476	/// - From the interpreter runtime stack by using [`LuaState::get_stack`].
477	/// - Pre-specified when [`DebugInfo`] is received from an [`Hook`]'s arguments (see [`Hook`]).
478	///
479	/// `n` selects which local to get, `1` being the first local and so on until the last local.
480	/// Negative values of `n` can be used to get vararg arguments.
481	///
482	/// Invalid values of `n` will result in the function returning `None` and not changing any local, but the top element will still be popped!
483	///
484	/// If the returned name is enclosed in round brackets, the changed local is an internal variable.
485	///
486	/// # Panics
487	///
488	/// Panics if none of the two ways of specifying a function are attempted or if the stack is empty.
489	pub fn set_local(&mut self, info: &DebugInfo, n: i32) -> Option<&CStr> {
490		assert!(self.get_top() > 0, "tried to set a local's value despite having an empty stack");
491		assert!(info.0.i_ci != 0, "tried to set a local's value without specifying a function");
492
493		// SAFETY: self.0 and info's pointer are always valid, and lua_setlocal returns valid nul-terminated string pointers when not null.
494		let local = unsafe { ffi::lua_setlocal(self.0, info.as_ptr(), n) };
495		map_ptr!(local, unsafe { CStr::from_ptr(local) })
496	}
497
498	/// Get information about the `n`th upvalue of the function at index `func_index`.
499	///
500	/// The upvalue's value is pushed onto the stack and its name is returned.
501	///
502	/// If the `n`th upvalue doesn't exist or the element at index `func_index` is not a function,
503	/// `None` is returned and nothing is pushed onto the stack.
504	///
505	/// If the function is a [`CFunction`], the returned upvalue name will be an empty string.
506	#[inline]
507	pub fn get_upvalue(&mut self, func_index: i32, n: u8) -> Option<&CStr> {
508		// SAFETY: self.0 is always valid and lua_getupvalue returns valid nul-terminated string pointers when not null.
509		let upvalue = unsafe { ffi::lua_getupvalue(self.0, func_index, i32::from(n)) };
510		map_ptr!(upvalue, unsafe { CStr::from_ptr(upvalue) })
511	}
512
513	/// Sets the value of the `n`th upvalue of the function at index `func_index` to the value of the top element (which is popped),
514	/// returning the upvalue's name.
515	///
516	/// If the `n`th upvalue doesn't exist or the element at index `func_index` is not a function,
517	/// `None` is returned and the upvalue is not changed (the top element will not be popped).
518	///
519	/// # Panics
520	///
521	/// Panics if the stack is empty.
522	#[inline]
523	pub fn set_upvalue(&mut self, func_index: i32, n: u8) -> Option<&CStr> {
524		assert!(self.get_top() > 0, "tried to set an upvalue's value despite having an empty stack");
525
526		// SAFETY: self.0 is always valid and lua_setupvalue returns valid nul-terminated string pointers when not null.
527		let upvalue = unsafe { ffi::lua_setupvalue(self.0, func_index, i32::from(n)) };
528		map_ptr!(upvalue, unsafe { CStr::from_ptr(upvalue) })
529	}
530
531	/// Returns `true` if the `n`th upvalue of the function at index `func_index` exists, `false` otherwise.
532	#[inline]
533	pub fn is_function_upvalue(&self, func_index: i32, n: u8) -> bool {
534		// SAFETY: No elements are popped except the one element that is pushed by this function.
535		unsafe { self.access_mut(|lua| {
536			let exists = lua.get_upvalue(func_index, n).is_some();
537
538			if exists {
539				// Remove the upvalue's value from the stack.
540				lua.pop(1);
541			}
542
543			exists
544		}) }
545	}
546
547	/// Returns an unique generic pointer for the `n`th upvalue of the function at index `func_index`.
548	///
549	/// Different upvalues will always return different pointers,
550	/// thus the pointers can be compared to see if different functions share the same upvalue.
551	///
552	/// If `func_index` or `n` are invalid a null pointer will be returned instead.
553	///
554	/// There is no intended way to convert the pointer to the upvalue itself.
555	#[inline]
556	pub fn upvalue_id(&self, func_index: i32, n: u8) -> *mut () {
557		if self.is_function_upvalue(func_index, n) {
558			// SAFETY: self.0 is always valid and func_index and n are also valid.
559			unsafe { ffi::lua_upvalueid(self.0, func_index, i32::from(n)).cast() }
560		} else {
561			ptr::null_mut()
562		}
563	}
564
565	/// Returns the current [`Hook`], or `None` if no hook is currently enabled.
566	///
567	/// [`lua_Hook`] is returned instead of [`Hook`] as this function cannot determine its safety.
568	#[inline]
569	pub fn get_hook(&self) -> Option<lua_Hook> {
570		// SAFETY: self.0 is always valid.
571		unsafe { ffi::lua_gethook(self.0) }
572	}
573
574	/// Sets a new debugging [`Hook`] function, replacing the previous hook (see [`Hook`]).
575	///
576	/// `mask` specifies which [`HookEvent`]s can call `hook`,
577	/// the "mask value" of an [`HookEvent`] can be obtained from [`HookEvent::as_mask`] or from the `HookEvent::MASK_*` constants.
578	/// Different mask values can be bit or'd together so that the hook can be called from different events.
579	///
580	/// If `mask` is `0` or invalid, this function behaves the same as [`LuaState::unset_hook`].
581	///
582	/// If [`HookEvent::Count`] is one of the possible events for this hook, `count` specifies the amounts of instructions inbetween each call
583	/// (it's ignored otherwise).
584	///
585	/// # Examples
586	///
587	/// ```
588	/// # use low_luajit::{LuaState, DebugInfo, HookEvent};
589	/// extern "C-unwind" fn example_hook(lua: LuaState, info: &mut DebugInfo) {
590	///     println!("Hook called by {:?}!", info.event());
591	/// }
592	///
593	/// # fn example(lua: LuaState) {
594	/// lua.set_hook(example_hook, HookEvent::MASK_CALL | HookEvent::MASK_RETURN, 0);
595	/// # }
596	/// ```
597	#[inline]
598	pub fn set_hook(&self, hook: Hook, mask: i32, count: i32) {
599		// SAFETY: self.0 is always valid and hook will be called properly.
600		unsafe { ffi::lua_sethook(self.0, Some(hook.to_raw()), mask, count); }
601	}
602
603	/// Disables the current [`Hook`], without replacing it with another.
604	///
605	/// To replace it with a new one instead, see [`LuaState::set_hook`].
606	#[inline]
607	pub fn unset_hook(&self) {
608		// SAFETY: self.0 is always valid.
609		unsafe { ffi::lua_sethook(self.0, None, 0, 0); }
610	}
611
612	/// Returns the current [`Hook`]'s mask value.
613	///
614	/// See [`LuaState::set_hook`] for more information.
615	#[inline]
616	pub fn get_hook_mask(&self) -> i32 {
617		// SAFETY: self.0 is always valid.
618		unsafe { ffi::lua_gethookmask(self.0) }
619	}
620
621	/// Sets the current [`Hook`]'s mask value.
622	///
623	/// See [`LuaState::set_hook`] for more information.
624	#[inline]
625	pub fn set_hook_mask(&self, mask: i32) {
626		// SAFETY: self.0 is always valid and we're not changing the hook.
627		unsafe { ffi::lua_sethook(self.0, self.get_hook(), mask, self.get_hook_count()); }
628	}
629
630	/// Returns the current [`Hook`]'s "count" (not the *current* count, simply the value that was specified).
631	///
632	/// See [`LuaState::set_hook`] for more information.
633	#[inline]
634	pub fn get_hook_count(&self) -> i32 {
635		// SAFETY: self.0 is always valid.
636		unsafe { ffi::lua_gethookcount(self.0) }
637	}
638
639	/// Sets the current [`Hook`]'s "count" (resetting its progress).
640	///
641	/// See [`LuaState::set_hook`] for more information.
642	#[inline]
643	pub fn set_hook_count(&self, count: i32) {
644		// SAFETY: self.0 is always valid and we're not changing the hook.
645		unsafe { ffi::lua_sethook(self.0, self.get_hook(), self.get_hook_mask(), count); }
646	}
647}