Update integer/number coercion logic

This commit is contained in:
Alex Orlenko 2022-05-30 19:26:12 +01:00
parent 3766cee4dd
commit a05a58b258
No known key found for this signature in database
GPG key ID: 4C150C250863B96D
3 changed files with 44 additions and 21 deletions

View file

@ -376,20 +376,24 @@ macro_rules! lua_convert_int {
#[inline]
fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
let ty = value.type_name();
(if let Value::Integer(i) = value {
cast(i)
} else if let Some(i) = lua.coerce_integer(value.clone())? {
cast(i)
} else {
cast(lua.coerce_number(value)?.ok_or_else(|| {
Error::FromLuaConversionError {
from: ty,
to: stringify!($x),
message: Some(
"expected number or string coercible to number".to_string(),
),
(match value {
Value::Integer(i) => cast(i),
Value::Number(n) => cast(n),
_ => {
if let Some(i) = lua.coerce_integer(value.clone())? {
cast(i)
} else {
cast(lua.coerce_number(value)?.ok_or_else(|| {
Error::FromLuaConversionError {
from: ty,
to: stringify!($x),
message: Some(
"expected number or string coercible to number".to_string(),
),
}
})?)
}
})?)
}
})
.ok_or_else(|| Error::FromLuaConversionError {
from: ty,

View file

@ -2304,15 +2304,29 @@ impl Lua {
ud
}
#[cfg(any(feature = "lua54", feature = "lua53"))]
ffi::LUA_TNUMBER => {
if ffi::lua_isinteger(state, -1) != 0 {
let i = Value::Integer(ffi::lua_tointeger(state, -1));
ffi::lua_pop(state, 1);
i
let v = if ffi::lua_isinteger(state, -1) != 0 {
Value::Integer(ffi::lua_tointeger(state, -1))
} else {
let n = Value::Number(ffi::lua_tonumber(state, -1));
ffi::lua_pop(state, 1);
n
Value::Number(ffi::lua_tonumber(state, -1))
};
ffi::lua_pop(state, 1);
v
}
#[cfg(any(
feature = "lua52",
feature = "lua51",
feature = "luajit",
feature = "luau"
))]
ffi::LUA_TNUMBER => {
let n = ffi::lua_tonumber(state, -1);
ffi::lua_pop(state, 1);
match num_traits::cast(n) {
Some(i) if (n - (i as Number)).abs() < Number::EPSILON => Value::Integer(i),
_ => Value::Number(n),
}
}

View file

@ -560,7 +560,12 @@ fn test_num_conversion() -> Result<()> {
assert_eq!(lua.load("1.0").eval::<f64>()?, 1.0);
#[cfg(any(feature = "lua54", feature = "lua53"))]
assert_eq!(lua.load("1.0").eval::<String>()?, "1.0");
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
#[cfg(any(
feature = "lua52",
feature = "lua51",
feature = "luajit",
feature = "luau"
))]
assert_eq!(lua.load("1.0").eval::<String>()?, "1");
assert_eq!(lua.load("1.5").eval::<i64>()?, 1);