Skip to content

Commit 3be4745

Browse files
committed
Add initial Luau integer64 type support
RFC: https://rfcs.luau.org/type-long-integer.html Unfortunately this type is not backward compatible with regular numbers and require a special "integer" library. It's not integrated with `Value` enum to keep it simple.
1 parent c52deec commit 3be4745

9 files changed

Lines changed: 70 additions & 13 deletions

File tree

mlua-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ cfg-if = "1.0"
4343
pkg-config = "0.3.17"
4444
lua-src = { version = ">= 550.1.0, < 550.2.0", optional = true }
4545
luajit-src = { version = ">= 210.7.0, < 210.8.0", optional = true }
46-
luau0-src = { version = "0.19.0", optional = true }
46+
luau0-src = { version = "0.20.0", optional = true }
4747

4848
[lints.rust]
4949
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(raw_dylib)'] }

mlua-sys/src/luau/lauxlib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ unsafe extern "C-unwind" {
3838

3939
#[link_name = "luaL_checkinteger"]
4040
pub fn luaL_checkinteger_(L: *mut lua_State, narg: c_int) -> c_int;
41+
pub fn luaL_checkinteger64(L: *mut lua_State, narg: c_int) -> i64;
4142
#[link_name = "luaL_optinteger"]
4243
pub fn luaL_optinteger_(L: *mut lua_State, narg: c_int, def: c_int) -> c_int;
44+
pub fn luaL_optinteger64(L: *mut lua_State, narg: c_int, def: i64) -> i64;
4345
pub fn luaL_checkunsigned(L: *mut lua_State, narg: c_int) -> lua_Unsigned;
4446
pub fn luaL_optunsigned(L: *mut lua_State, narg: c_int, def: lua_Unsigned) -> lua_Unsigned;
4547

mlua-sys/src/luau/lua.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,15 @@ pub const LUA_TBOOLEAN: c_int = 1;
6565

6666
pub const LUA_TLIGHTUSERDATA: c_int = 2;
6767
pub const LUA_TNUMBER: c_int = 3;
68-
pub const LUA_TVECTOR: c_int = 4;
68+
pub const LUA_TINTEGER: c_int = 4;
69+
pub const LUA_TVECTOR: c_int = 5;
6970

70-
pub const LUA_TSTRING: c_int = 5;
71-
pub const LUA_TTABLE: c_int = 6;
72-
pub const LUA_TFUNCTION: c_int = 7;
73-
pub const LUA_TUSERDATA: c_int = 8;
74-
pub const LUA_TTHREAD: c_int = 9;
75-
pub const LUA_TBUFFER: c_int = 10;
71+
pub const LUA_TSTRING: c_int = 6;
72+
pub const LUA_TTABLE: c_int = 7;
73+
pub const LUA_TFUNCTION: c_int = 8;
74+
pub const LUA_TUSERDATA: c_int = 9;
75+
pub const LUA_TTHREAD: c_int = 10;
76+
pub const LUA_TBUFFER: c_int = 11;
7677

7778
/// Guaranteed number of Lua stack slots available to a C function.
7879
pub const LUA_MINSTACK: c_int = 20;
@@ -153,6 +154,7 @@ unsafe extern "C-unwind" {
153154
pub fn lua_tounsignedx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Unsigned;
154155
pub fn lua_tovector(L: *mut lua_State, idx: c_int) -> *const c_float;
155156
pub fn lua_toboolean(L: *mut lua_State, idx: c_int) -> c_int;
157+
pub fn lua_tointeger64(L: *mut lua_State, idx: c_int, isinteger: *mut c_int) -> i64;
156158
pub fn lua_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char;
157159
pub fn lua_tostringatom(L: *mut lua_State, idx: c_int, atom: *mut c_int) -> *const c_char;
158160
pub fn lua_tolstringatom(
@@ -182,6 +184,7 @@ unsafe extern "C-unwind" {
182184
pub fn lua_pushnumber(L: *mut lua_State, n: lua_Number);
183185
#[link_name = "lua_pushinteger"]
184186
pub fn lua_pushinteger_(L: *mut lua_State, n: c_int);
187+
pub fn lua_pushinteger64(L: *mut lua_State, n: i64);
185188
pub fn lua_pushunsigned(L: *mut lua_State, n: lua_Unsigned);
186189
#[cfg(not(feature = "luau-vector4"))]
187190
pub fn lua_pushvector(L: *mut lua_State, x: c_float, y: c_float, z: c_float);
@@ -412,6 +415,11 @@ pub unsafe fn lua_isboolean(L: *mut lua_State, n: c_int) -> c_int {
412415
(lua_type(L, n) == LUA_TBOOLEAN) as c_int
413416
}
414417

418+
#[inline(always)]
419+
pub unsafe fn lua_isinteger64(L: *mut lua_State, n: c_int) -> c_int {
420+
(lua_type(L, n) == LUA_TINTEGER) as c_int
421+
}
422+
415423
#[inline(always)]
416424
pub unsafe fn lua_isvector(L: *mut lua_State, n: c_int) -> c_int {
417425
(lua_type(L, n) == LUA_TVECTOR) as c_int

mlua-sys/src/luau/luacode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ unsafe extern "C" {
8080
pub fn luau_set_compile_constant_nil(cons: *mut lua_CompileConstant);
8181
pub fn luau_set_compile_constant_boolean(cons: *mut lua_CompileConstant, b: c_int);
8282
pub fn luau_set_compile_constant_number(cons: *mut lua_CompileConstant, n: f64);
83+
pub fn luau_set_compile_constant_integer64(cons: *mut lua_CompileConstant, l: i64);
8384
pub fn luau_set_compile_constant_vector(cons: *mut lua_CompileConstant, x: f32, y: f32, z: f32, w: f32);
8485
pub fn luau_set_compile_constant_string(cons: *mut lua_CompileConstant, s: *const c_char, l: usize);
8586
}

mlua-sys/src/luau/lualib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub const LUA_UTF8LIBNAME: *const c_char = cstr!("utf8");
1414
pub const LUA_MATHLIBNAME: *const c_char = cstr!("math");
1515
pub const LUA_DBLIBNAME: *const c_char = cstr!("debug");
1616
pub const LUA_VECLIBNAME: *const c_char = cstr!("vector");
17+
pub const LUA_INTLIBNAME : *const c_char = cstr!("integer");
1718

1819
unsafe extern "C-unwind" {
1920
pub fn luaopen_base(L: *mut lua_State) -> c_int;
@@ -27,6 +28,7 @@ unsafe extern "C-unwind" {
2728
pub fn luaopen_math(L: *mut lua_State) -> c_int;
2829
pub fn luaopen_debug(L: *mut lua_State) -> c_int;
2930
pub fn luaopen_vector(L: *mut lua_State) -> c_int;
31+
pub fn luaopen_integer(L: *mut lua_State) -> c_int;
3032

3133
// open all builtin libraries
3234
pub fn luaL_openlibs(L: *mut lua_State);

src/conversion.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,13 @@ macro_rules! lua_convert_int {
812812
});
813813
}
814814
}
815+
#[cfg(feature = "luau")]
816+
if type_id == ffi::LUA_TINTEGER {
817+
let i = ffi::lua_tointeger64(state, idx, std::ptr::null_mut());
818+
return cast(i).ok_or_else(|| {
819+
Error::from_lua_conversion("integer", stringify!($x), "out of range".to_string())
820+
});
821+
}
815822
// Fallback to default
816823
Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua())
817824
}

src/state/raw.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -817,15 +817,22 @@ impl RawLua {
817817

818818
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit", feature = "luau"))]
819819
ffi::LUA_TNUMBER => {
820-
use crate::types::Number;
821-
822820
let n = ffi::lua_tonumber(state, idx);
823821
match num_traits::cast(n) {
824-
Some(i) if n.to_bits() == (i as Number).to_bits() => Value::Integer(i),
822+
Some(i) if n.to_bits() == (i as crate::types::Number).to_bits() => Value::Integer(i),
825823
_ => Value::Number(n),
826824
}
827825
}
828826

827+
#[cfg(feature = "luau")]
828+
ffi::LUA_TINTEGER => {
829+
let i = ffi::lua_tointeger64(state, idx, ptr::null_mut());
830+
match num_traits::cast(i) {
831+
Some(i) => Value::Integer(i),
832+
_ => Value::Number(i as crate::types::Number),
833+
}
834+
}
835+
829836
#[cfg(feature = "luau")]
830837
ffi::LUA_TVECTOR => {
831838
let v = ffi::lua_tovector(state, idx);
@@ -1598,6 +1605,11 @@ unsafe fn load_std_libs(state: *mut ffi::lua_State, libs: StdLib) -> Result<()>
15981605
requiref(state, ffi::LUA_VECLIBNAME, ffi::luaopen_vector, 1)?;
15991606
}
16001607

1608+
#[cfg(feature = "luau")]
1609+
if libs.contains(StdLib::INTEGER) {
1610+
requiref(state, ffi::LUA_INTLIBNAME, ffi::luaopen_integer, 1)?;
1611+
}
1612+
16011613
if libs.contains(StdLib::MATH) {
16021614
requiref(state, ffi::LUA_MATHLIBNAME, ffi::luaopen_math, 1)?;
16031615
}

src/stdlib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,15 @@ impl StdLib {
7373
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
7474
pub const VECTOR: StdLib = StdLib(1 << 10);
7575

76+
/// [`integer`](https://luau.org/library#integer-library) library
77+
#[cfg(any(feature = "luau", doc))]
78+
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
79+
pub const INTEGER: StdLib = StdLib(1 << 11);
80+
7681
/// [`jit`](http://luajit.org/ext_jit.html) library
7782
#[cfg(any(feature = "luajit", doc))]
7883
#[cfg_attr(docsrs, doc(cfg(feature = "luajit")))]
79-
pub const JIT: StdLib = StdLib(1 << 11);
84+
pub const JIT: StdLib = StdLib(1 << 12);
8085

8186
/// (**unsafe**) [`ffi`](http://luajit.org/ext_ffi.html) library
8287
#[cfg(any(feature = "luajit", doc))]

tests/luau.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use std::os::raw::c_void;
66
use std::sync::Arc;
77
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU64, Ordering};
88

9-
use mlua::{Compiler, Error, Function, Lua, LuaOptions, Result, StdLib, Table, Value, Vector, VmState};
9+
use mlua::{
10+
Compiler, Error, Function, Lua, LuaOptions, ObjectLike, Result, StdLib, Table, Value, Vector, VmState,
11+
};
1012

1113
#[test]
1214
fn test_version() -> Result<()> {
@@ -533,5 +535,23 @@ fn test_heap_dump() -> Result<()> {
533535
Ok(())
534536
}
535537

538+
#[test]
539+
fn test_integer64_type() -> Result<()> {
540+
let lua = Lua::new();
541+
542+
_ = Lua::set_fflag("LuauIntegerType", true);
543+
544+
let integer_lib = lua.globals().get::<Table>("integer")?;
545+
let n = integer_lib.call_function::<i64>("create", 42)?;
546+
assert_eq!(n, 42);
547+
548+
let n: i64 = lua.load("return 42i").eval()?;
549+
assert_eq!(n, 42);
550+
let n: i64 = lua.load("return -42i").eval()?;
551+
assert_eq!(n, -42);
552+
553+
Ok(())
554+
}
555+
536556
#[path = "luau/require.rs"]
537557
mod require;

0 commit comments

Comments
 (0)