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