use crate::LuaType;
use crate::Result;
use crate::State;
use crate::error::ArgError;
use crate::error::ErrorKind;
use crate::lua_std;
impl State {
pub fn check_any(&mut self, arg_number: isize) -> Result<()> {
assert!(arg_number != 0);
if self.get_top() < arg_number.unsigned_abs() {
let e = ArgError {
arg_number,
func_name: None,
expected: None,
received: None,
};
Err(self.error(ErrorKind::ArgError(e)))
} else {
Ok(())
}
}
pub fn check_type(&mut self, arg_number: isize, expected_type: LuaType) -> Result<()> {
assert!(arg_number != 0);
if self.get_top() < arg_number.unsigned_abs() {
let e = ArgError {
arg_number,
func_name: None,
expected: Some(expected_type),
received: None,
};
return Err(self.error(ErrorKind::ArgError(e)));
}
let received_type = self.typ(arg_number);
if received_type != expected_type {
let e = ArgError {
arg_number,
func_name: None,
expected: Some(expected_type),
received: Some(received_type),
};
return Err(self.error(ErrorKind::ArgError(e)));
}
Ok(())
}
pub(crate) fn is_none_or_nil(&self, arg_number: isize) -> bool {
assert!(arg_number != 0);
self.get_top() < arg_number.unsigned_abs() || self.typ(arg_number) == LuaType::Nil
}
pub(crate) fn check_optional_type(
&mut self,
arg_number: isize,
expected_type: LuaType,
) -> Result<bool> {
if self.is_none_or_nil(arg_number) {
return Ok(false);
}
self.check_type(arg_number, expected_type)?;
Ok(true)
}
#[hotpath::measure]
pub fn open_libs(&mut self) -> Result<()> {
lua_std::open_libs(self)?;
self.capture_table_library_fallback();
#[cfg(feature = "snapshot")]
self.capture_env_tokens();
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn optional_type_treats_missing_and_nil_as_absent() {
let mut state = State::new();
assert!(
!state
.check_optional_type(1, LuaType::Number)
.expect("missing optional argument must be accepted")
);
state
.push_nil()
.expect("an empty stack has room for one value");
assert!(
!state
.check_optional_type(1, LuaType::Number)
.expect("nil optional argument must be accepted")
);
}
#[test]
fn optional_type_preserves_non_nil_arg_error() {
let mut state = State::new();
state
.push_string("wrong type")
.expect("short test string fits");
let optional = state
.check_optional_type(1, LuaType::Number)
.expect_err("wrong optional argument type must fail");
let required = state
.check_type(1, LuaType::Number)
.expect_err("wrong required argument type must fail");
let (ErrorKind::ArgError(optional), ErrorKind::ArgError(required)) =
(&optional.kind, &required.kind)
else {
panic!("both checks must produce argument errors");
};
assert_eq!(optional.arg_number, required.arg_number);
assert_eq!(optional.expected, required.expected);
assert_eq!(optional.received, required.received);
assert_eq!(optional.func_name, required.func_name);
}
}