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.0 is always valid.
10 unsafe { ffi::lua_isnumber(self.0, 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.0 is always valid.
22 unsafe { ffi::lua_tonumber(self.0, 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.0 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.0, 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.0 is always valid.
50 unsafe { ffi::lua_tointeger(self.0, 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.0 is always valid.
64 let mut is_num = 0;
65 let integer = unsafe { ffi::lua_tointegerx(self.0, 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.0 is always valid.
73 unsafe { ffi::lua_pushnumber(self.0, 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.0 is always valid.
80 unsafe { ffi::lua_pushinteger(self.0, 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 pub fn check_number(&self, arg_n: i32) -> f64 {
92 // SAFETY: self.0 is always valid.
93 unsafe { ffi::luaL_checknumber(self.0, arg_n) }
94 }
95
96 /// Checks if there's a number at the given index `arg_n` and returns it as an integer.
97 ///
98 /// If the check fails, [`LuaState::type_error`] is called using `arg_n`.
99 ///
100 /// # Lua Errors
101 ///
102 /// Intentionally errors if the check fails.
103 #[inline]
104 pub fn check_integer(&self, arg_n: i32) -> isize {
105 // SAFETY: self.0 is always valid.
106 unsafe { ffi::luaL_checkinteger(self.0, arg_n) }
107 }
108
109 /// Behaves exactly as [`LuaState::check_number`],
110 /// but returns `default` instead of erroring when the element at the given index `arg_n` is `nil` (or non-existing).
111 #[inline]
112 pub fn opt_number(&self, arg_n: i32, default: f64) -> f64 {
113 // SAFETY: self.0 is always valid.
114 unsafe { ffi::luaL_optnumber(self.0, arg_n, default) }
115 }
116
117 /// Behaves exactly as [`LuaState::check_integer`],
118 /// but returns `default` instead of erroring when the element at the given index `arg_n` is `nil` (or non-existing).
119 #[inline]
120 pub fn opt_integer(&self, arg_n: i32, default: isize) -> isize {
121 // SAFETY: self.0 is always valid.
122 unsafe { ffi::luaL_optinteger(self.0, arg_n, default) }
123 }
124
125 /// Finishes the currently called [`CFunction`], returning the given `number` to the caller.
126 ///
127 /// The `LuaState` wrapper is consumed to prevent invalidating the `AmountReturned` (the Lua state itself is left intact).
128 ///
129 /// [`CFunction`]: ./type.CFunction.html
130 #[inline]
131 pub fn return_number(mut self, number: f64) -> AmountReturned {
132 self.push_number(number);
133
134 // SAFETY: There should always be at least one element in the stack.
135 unsafe { AmountReturned::unchecked(1) }
136 }
137
138 /// Finishes the currently called [`CFunction`], returning the given `integer` to the caller.
139 ///
140 /// The `LuaState` wrapper is consumed to prevent invalidating the `AmountReturned` (the Lua state itself is left intact).
141 ///
142 /// [`CFunction`]: ./type.CFunction.html
143 #[inline]
144 pub fn return_integer(mut self, integer: isize) -> AmountReturned {
145 self.push_integer(integer);
146
147 // SAFETY: There should always be at least one element in the stack.
148 unsafe { AmountReturned::unchecked(1) }
149 }
150}