1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use crate::{AmountReturned, LuaState, ffi};
/// Number related functions.
impl LuaState {
/// Returns `true` if the value at the given acceptable `index` is a number, `false` otherwise.
#[inline]
#[must_use]
pub fn is_number(&self, index: i32) -> bool {
// SAFETY: self.0 is always valid.
unsafe { ffi::lua_isnumber(self.0, index) != 0 }
}
/// Converts the value at the given acceptable `index` to a number and returns it.
///
/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `0.0`.
///
/// This conversion *does not* affect the element in the stack itself (it stays as is).
#[inline]
#[must_use]
pub fn to_number(&self, index: i32) -> f64 {
// SAFETY: self.0 is always valid.
unsafe { ffi::lua_tonumber(self.0, index) }
}
/// Converts the value at the given acceptable `index` to a number and returns it.
///
/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `None`.
///
/// This conversion *does not* affect the element in the stack itself (it stays as is).
#[inline]
#[must_use]
pub fn to_number_x(&self, index: i32) -> Option<f64> {
// SAFETY: self.0 is always valid and is_num is initialized right before passing its pointer.
let mut is_num = 0;
let number = unsafe { ffi::lua_tonumberx(self.0, index, &raw mut is_num) };
(is_num != 0).then_some(number)
}
/// Converts the value at the given acceptable `index` to an integer and returns it.
///
/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `0`.
///
/// If the number is not an integer, it will be truncated in an unspecified way.
///
/// This conversion *does not* affect the element in the stack itself (it stays as is).
#[inline]
#[must_use]
pub fn to_integer(&self, index: i32) -> isize {
// SAFETY: self.0 is always valid.
unsafe { ffi::lua_tointeger(self.0, index) }
}
/// Converts the value at the given acceptable `index` to an integer and returns it.
///
/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `0`.
///
/// If the number is not an integer, it will be truncated in an unspecified way.
///
/// This conversion *does not* affect the element in the stack itself (it stays as is).
#[inline]
#[must_use]
pub fn to_integer_x(&self, index: i32) -> Option<isize> {
// SAFETY: self.0 is always valid.
let mut is_num = 0;
let integer = unsafe { ffi::lua_tointegerx(self.0, index, &raw mut is_num) };
(is_num != 0).then_some(integer)
}
/// Pushes the given `number` onto the stack.
#[inline]
pub fn push_number(&mut self, number: f64) {
// SAFETY: self.0 is always valid.
unsafe { ffi::lua_pushnumber(self.0, number); }
}
/// Pushes the given `integer` onto the stack.
#[inline]
pub fn push_integer(&mut self, integer: isize) {
// SAFETY: self.0 is always valid.
unsafe { ffi::lua_pushinteger(self.0, integer); }
}
/// Checks if there's a number at the given index `arg_n` and returns it.
///
/// If the check fails, [`LuaState::type_error`] is called using `arg_n`.
///
/// # Lua Errors
///
/// Intentionally errors if the check fails.
#[inline]
pub fn check_number(&self, arg_n: i32) -> f64 {
// SAFETY: self.0 is always valid.
unsafe { ffi::luaL_checknumber(self.0, arg_n) }
}
/// Checks if there's a number at the given index `arg_n` and returns it as an integer.
///
/// If the check fails, [`LuaState::type_error`] is called using `arg_n`.
///
/// # Lua Errors
///
/// Intentionally errors if the check fails.
#[inline]
pub fn check_integer(&self, arg_n: i32) -> isize {
// SAFETY: self.0 is always valid.
unsafe { ffi::luaL_checkinteger(self.0, arg_n) }
}
/// Behaves exactly as [`LuaState::check_number`],
/// but returns `default` instead of erroring when the element at the given index `arg_n` is `nil` (or non-existing).
#[inline]
pub fn opt_number(&self, arg_n: i32, default: f64) -> f64 {
// SAFETY: self.0 is always valid.
unsafe { ffi::luaL_optnumber(self.0, arg_n, default) }
}
/// Behaves exactly as [`LuaState::check_integer`],
/// but returns `default` instead of erroring when the element at the given index `arg_n` is `nil` (or non-existing).
#[inline]
pub fn opt_integer(&self, arg_n: i32, default: isize) -> isize {
// SAFETY: self.0 is always valid.
unsafe { ffi::luaL_optinteger(self.0, arg_n, default) }
}
/// Finishes the currently called [`CFunction`], returning the given `number` to the caller.
///
/// The `LuaState` wrapper is consumed to prevent invalidating the `AmountReturned` (the Lua state itself is left intact).
///
/// [`CFunction`]: ./type.CFunction.html
#[inline]
pub fn return_number(mut self, number: f64) -> AmountReturned {
self.push_number(number);
// SAFETY: There should always be at least one element in the stack.
unsafe { AmountReturned::unchecked(1) }
}
/// Finishes the currently called [`CFunction`], returning the given `integer` to the caller.
///
/// The `LuaState` wrapper is consumed to prevent invalidating the `AmountReturned` (the Lua state itself is left intact).
///
/// [`CFunction`]: ./type.CFunction.html
#[inline]
pub fn return_integer(mut self, integer: isize) -> AmountReturned {
self.push_integer(integer);
// SAFETY: There should always be at least one element in the stack.
unsafe { AmountReturned::unchecked(1) }
}
}