Add Lua 5.4 (rc2) support

This commit is contained in:
Alex Orlenko 2020-05-08 12:42:40 +01:00
parent 5c226b4915
commit 539b569ff4
15 changed files with 181 additions and 58 deletions

View File

@ -22,6 +22,19 @@ pub fn probe_lua() -> PathBuf {
// Find using via pkg-config // Find using via pkg-config
#[cfg(feature = "lua54")]
{
let mut lua = pkg_config::Config::new()
.range_version((Bound::Included("5.4"), Bound::Excluded("5.5")))
.probe("lua");
if lua.is_err() {
lua = pkg_config::Config::new().probe("lua5.4");
}
return lua.unwrap().include_paths[0].clone();
}
#[cfg(feature = "lua53")] #[cfg(feature = "lua53")]
{ {
let mut lua = pkg_config::Config::new() let mut lua = pkg_config::Config::new()

View File

@ -1,11 +1,18 @@
use std::path::PathBuf; use std::path::PathBuf;
#[cfg(any(feature = "lua53", feature = "lua52", feature = "lua51"))] #[cfg(any(
feature = "lua54",
feature = "lua53",
feature = "lua52",
feature = "lua51"
))]
use lua_src; use lua_src;
#[cfg(feature = "luajit")] #[cfg(feature = "luajit")]
use luajit_src; use luajit_src;
pub fn probe_lua() -> PathBuf { pub fn probe_lua() -> PathBuf {
#[cfg(feature = "lua54")]
let artifacts = lua_src::Build::new().build(lua_src::Lua54);
#[cfg(feature = "lua53")] #[cfg(feature = "lua53")]
let artifacts = lua_src::Build::new().build(lua_src::Lua53); let artifacts = lua_src::Build::new().build(lua_src::Lua53);
#[cfg(feature = "lua52")] #[cfg(feature = "lua52")]

View File

@ -59,27 +59,36 @@ fn build_glue<P: AsRef<Path> + std::fmt::Debug>(include_path: &P) {
fn main() { fn main() {
#[cfg(not(any( #[cfg(not(any(
feature = "lua54",
feature = "lua53", feature = "lua53",
feature = "lua52", feature = "lua52",
feature = "lua51", feature = "lua51",
feature = "luajit" feature = "luajit"
)))] )))]
panic!("You must enable one of the features: lua53, lua52, lua51, luajit"); panic!("You must enable one of the features: lua54, lua53, lua52, lua51, luajit");
#[cfg(all(
feature = "lua54",
any(
feature = "lua53",
feature = "lua52",
feature = "lua51",
feature = "luajit"
)
))]
panic!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
#[cfg(all( #[cfg(all(
feature = "lua53", feature = "lua53",
any(feature = "lua52", feature = "lua51", feature = "luajit") any(feature = "lua52", feature = "lua51", feature = "luajit")
))] ))]
panic!("You can enable only one of the features: lua53, lua52, lua51, luajit"); panic!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
#[cfg(all(feature = "lua52", any(feature = "lua51", feature = "luajit")))] #[cfg(all(feature = "lua52", any(feature = "lua51", feature = "luajit")))]
panic!("You can enable only one of the features: lua53, lua52, lua51, luajit"); panic!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
#[cfg(all(feature = "lua51", feature = "luajit"))] #[cfg(all(feature = "lua51", feature = "luajit"))]
panic!("You can enable only one of the features: lua53, lua52, lua51, luajit"); panic!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
#[cfg(all(feature = "lua51", feature = "luajit"))]
panic!("You can enable only one of the features: lua53, lua52, lua51, luajit");
let include_dir = find::probe_lua(); let include_dir = find::probe_lua();
build_glue(&include_dir); build_glue(&include_dir);

View File

@ -73,7 +73,7 @@ pub use crate::ffi::lua_State;
pub use crate::error::{Error, ExternalError, ExternalResult, Result}; pub use crate::error::{Error, ExternalError, ExternalResult, Result};
pub use crate::function::Function; pub use crate::function::Function;
pub use crate::lua::{Chunk, Lua}; pub use crate::lua::{Chunk, GCMode, Lua};
pub use crate::multi::Variadic; pub use crate::multi::Variadic;
pub use crate::scope::Scope; pub use crate::scope::Scope;
pub use crate::stdlib::StdLib; pub use crate::stdlib::StdLib;

View File

@ -57,14 +57,28 @@ struct ExtraData {
ref_free: Vec<c_int>, ref_free: Vec<c_int>,
} }
#[cfg(feature = "send")] /// Mode of the Lua garbage collector (GC).
unsafe impl Send for Lua {} ///
/// In Lua 5.4 GC can work in two modes: incremental and generational.
/// Previous Lua versions support only incremental GC.
///
/// More information can be found in the Lua 5.x [documentation][lua_doc].
///
/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5
pub enum GCMode {
Incremental,
#[cfg(feature = "lua54")]
Generational,
}
#[cfg(feature = "async")] #[cfg(feature = "async")]
pub(crate) struct AsyncPollPending; pub(crate) struct AsyncPollPending;
#[cfg(feature = "async")] #[cfg(feature = "async")]
pub(crate) static WAKER_REGISTRY_KEY: u8 = 0; pub(crate) static WAKER_REGISTRY_KEY: u8 = 0;
#[cfg(feature = "send")]
unsafe impl Send for Lua {}
impl Drop for Lua { impl Drop for Lua {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
@ -224,7 +238,7 @@ impl Lua {
} }
/// Returns true if the garbage collector is currently running automatically. /// Returns true if the garbage collector is currently running automatically.
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
pub fn gc_is_running(&self) -> bool { pub fn gc_is_running(&self) -> bool {
unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCISRUNNING, 0) != 0 } unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCISRUNNING, 0) != 0 }
} }
@ -287,13 +301,78 @@ impl Lua {
/// Sets the 'step multiplier' value of the collector. /// Sets the 'step multiplier' value of the collector.
/// ///
/// Returns the previous value of the 'step multiplier'. More information can be found in the /// Returns the previous value of the 'step multiplier'. More information can be found in the
/// [Lua 5.3 documentation][lua_doc]. /// Lua 5.x [documentation][lua_doc].
/// ///
/// [lua_doc]: https://www.lua.org/manual/5.3/manual.html#2.5 /// [lua_doc]: https://www.lua.org/manual/5.3/manual.html#2.5
pub fn gc_set_step_multiplier(&self, step_multiplier: c_int) -> c_int { pub fn gc_set_step_multiplier(&self, step_multiplier: c_int) -> c_int {
unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSETSTEPMUL, step_multiplier) } unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSETSTEPMUL, step_multiplier) }
} }
/// Changes the collector to incremental mode with the given parameters.
///
/// Returns the previous mode (always `GCMode::Incremental` in Lua < 5.4).
/// More information can be found in the Lua 5.x [documentation][lua_doc].
///
/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5.1
pub fn gc_inc(&self, pause: c_int, step_multiplier: c_int, step_size: c_int) -> GCMode {
#[cfg(any(
feature = "lua53",
feature = "lua52",
feature = "lua51",
feature = "luajit"
))]
{
if pause > 0 {
unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSETPAUSE, pause) };
}
if step_multiplier > 0 {
unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSETSTEPMUL, step_multiplier) };
}
let _ = step_size; // Ignored
return GCMode::Incremental;
}
#[cfg(feature = "lua54")]
let prev_mode = unsafe {
ffi::lua_gc(
self.main_state,
ffi::LUA_GCSETPAUSE,
pause,
step_multiplier,
step_size,
)
};
#[cfg(feature = "lua54")]
match prev_mode {
ffi::LUA_GCINC => GCMode::Incremental,
ffi::LUA_GCGEN => GCMode::Generational,
_ => unreachable!(),
}
}
/// Changes the collector to generational mode with the given parameters.
///
/// Returns the previous mode. More information about the generational GC
/// can be found in the Lua 5.4 [documentation][lua_doc].
///
/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5.2
#[cfg(feature = "lua54")]
pub fn gc_gen(&self, minor_multiplier: c_int, major_multiplier: c_int) -> GCMode {
let prev_mode = unsafe {
ffi::lua_gc(
self.main_state,
ffi::LUA_GCGEN,
minor_multiplier,
major_multiplier,
)
};
match prev_mode {
ffi::LUA_GCGEN => GCMode::Generational,
ffi::LUA_GCINC => GCMode::Incremental,
_ => unreachable!(),
}
}
/// Returns Lua source code as a `Chunk` builder type. /// Returns Lua source code as a `Chunk` builder type.
/// ///
/// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or
@ -343,7 +422,7 @@ impl Lua {
ffi::LUA_OK => { ffi::LUA_OK => {
if let Some(env) = env { if let Some(env) = env {
self.push_value(env)?; self.push_value(env)?;
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
ffi::lua_setupvalue(self.state, -2, 1); ffi::lua_setupvalue(self.state, -2, 1);
#[cfg(any(feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua51", feature = "luajit"))]
ffi::lua_setfenv(self.state, -2); ffi::lua_setfenv(self.state, -2);
@ -595,7 +674,7 @@ impl Lua {
unsafe { unsafe {
let _sg = StackGuard::new(self.state); let _sg = StackGuard::new(self.state);
assert_stack(self.state, 2); assert_stack(self.state, 2);
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS); ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
#[cfg(any(feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua51", feature = "luajit"))]
ffi::lua_pushvalue(self.state, ffi::LUA_GLOBALSINDEX); ffi::lua_pushvalue(self.state, ffi::LUA_GLOBALSINDEX);
@ -1214,7 +1293,7 @@ impl Lua {
where where
'lua: 'callback, 'lua: 'callback,
{ {
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
self.load_from_std_lib(StdLib::COROUTINE)?; self.load_from_std_lib(StdLib::COROUTINE)?;
unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int { unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int {
@ -1521,7 +1600,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
} }
unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) { unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) {
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
{ {
if libs.contains(StdLib::COROUTINE) { if libs.contains(StdLib::COROUTINE) {
let colib_name = CString::new(ffi::LUA_COLIBNAME).unwrap(); let colib_name = CString::new(ffi::LUA_COLIBNAME).unwrap();
@ -1554,7 +1633,7 @@ unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) {
ffi::lua_pop(state, 1); ffi::lua_pop(state, 1);
} }
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
{ {
if libs.contains(StdLib::UTF8) { if libs.contains(StdLib::UTF8) {
let utf8lib_name = CString::new(ffi::LUA_UTF8LIBNAME).unwrap(); let utf8lib_name = CString::new(ffi::LUA_UTF8LIBNAME).unwrap();

View File

@ -3,12 +3,13 @@
pub use crate::{ pub use crate::{
AnyUserData as LuaAnyUserData, Chunk as LuaChunk, Error as LuaError, AnyUserData as LuaAnyUserData, Chunk as LuaChunk, Error as LuaError,
ExternalError as LuaExternalError, ExternalResult as LuaExternalResult, FromLua, FromLuaMulti, ExternalError as LuaExternalError, ExternalResult as LuaExternalResult, FromLua, FromLuaMulti,
Function as LuaFunction, Integer as LuaInteger, LightUserData as LuaLightUserData, Lua, Function as LuaFunction, GCMode as LuaGCMode, Integer as LuaInteger,
MetaMethod as LuaMetaMethod, MultiValue as LuaMultiValue, Nil as LuaNil, Number as LuaNumber, LightUserData as LuaLightUserData, Lua, MetaMethod as LuaMetaMethod,
RegistryKey as LuaRegistryKey, Result as LuaResult, String as LuaString, Table as LuaTable, MultiValue as LuaMultiValue, Nil as LuaNil, Number as LuaNumber, RegistryKey as LuaRegistryKey,
TableExt as LuaTableExt, TablePairs as LuaTablePairs, TableSequence as LuaTableSequence, Result as LuaResult, String as LuaString, Table as LuaTable, TableExt as LuaTableExt,
Thread as LuaThread, ThreadStatus as LuaThreadStatus, ToLua, ToLuaMulti, TablePairs as LuaTablePairs, TableSequence as LuaTableSequence, Thread as LuaThread,
UserData as LuaUserData, UserDataMethods as LuaUserDataMethods, Value as LuaValue, ThreadStatus as LuaThreadStatus, ToLua, ToLuaMulti, UserData as LuaUserData,
UserDataMethods as LuaUserDataMethods, Value as LuaValue,
}; };
#[cfg(feature = "async")] #[cfg(feature = "async")]

View File

@ -282,7 +282,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
assert_stack(lua.state, 6); assert_stack(lua.state, 6);
push_userdata(lua.state, ())?; push_userdata(lua.state, ())?;
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
ffi::lua_pushlightuserdata(lua.state, data.as_ptr() as *mut c_void); ffi::lua_pushlightuserdata(lua.state, data.as_ptr() as *mut c_void);
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
protect_lua_closure(lua.state, 0, 1, |state| { protect_lua_closure(lua.state, 0, 1, |state| {
@ -383,7 +383,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
// We know the destructor has not run yet because we hold a reference to the callback. // We know the destructor has not run yet because we hold a reference to the callback.
// First, get the environment table // First, get the environment table
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
ffi::lua_getupvalue(state, -1, 1); ffi::lua_getupvalue(state, -1, 1);
#[cfg(any(feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua51", feature = "luajit"))]
ffi::lua_getfenv(state, -1); ffi::lua_getfenv(state, -1);

View File

@ -6,13 +6,13 @@ use std::u32;
pub struct StdLib(u32); pub struct StdLib(u32);
impl StdLib { impl StdLib {
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
pub const COROUTINE: StdLib = StdLib(1 << 0); pub const COROUTINE: StdLib = StdLib(1 << 0);
pub const TABLE: StdLib = StdLib(1 << 1); pub const TABLE: StdLib = StdLib(1 << 1);
pub const IO: StdLib = StdLib(1 << 2); pub const IO: StdLib = StdLib(1 << 2);
pub const OS: StdLib = StdLib(1 << 3); pub const OS: StdLib = StdLib(1 << 3);
pub const STRING: StdLib = StdLib(1 << 4); pub const STRING: StdLib = StdLib(1 << 4);
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
pub const UTF8: StdLib = StdLib(1 << 5); pub const UTF8: StdLib = StdLib(1 << 5);
#[cfg(any(feature = "lua52", feature = "luajit"))] #[cfg(any(feature = "lua52", feature = "luajit"))]
pub const BIT: StdLib = StdLib(1 << 6); pub const BIT: StdLib = StdLib(1 << 6);

View File

@ -129,7 +129,9 @@ impl<'lua> Thread<'lua> {
} }
ffi::lua_xmove(lua.state, thread_state, nargs); ffi::lua_xmove(lua.state, thread_state, nargs);
let ret = ffi::lua_resume(thread_state, lua.state, nargs); let mut nresults = 0;
let ret = ffi::lua_resume(thread_state, lua.state, nargs, &mut nresults as *mut c_int);
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD { if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
protect_lua_closure(lua.state, 0, 0, |_| { protect_lua_closure(lua.state, 0, 0, |_| {
error_traceback(thread_state); error_traceback(thread_state);
@ -138,7 +140,6 @@ impl<'lua> Thread<'lua> {
return Err(pop_error(thread_state, ret)); return Err(pop_error(thread_state, ret));
} }
let nresults = ffi::lua_gettop(thread_state);
let mut results = MultiValue::new(); let mut results = MultiValue::new();
ffi::lua_xmove(thread_state, lua.state, nresults); ffi::lua_xmove(thread_state, lua.state, nresults);

View File

@ -34,25 +34,25 @@ pub enum MetaMethod {
Pow, Pow,
/// The unary minus (`-`) operator. /// The unary minus (`-`) operator.
Unm, Unm,
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
/// The floor division (//) operator. /// The floor division (//) operator.
IDiv, IDiv,
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
/// The bitwise AND (&) operator. /// The bitwise AND (&) operator.
BAnd, BAnd,
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
/// The bitwise OR (|) operator. /// The bitwise OR (|) operator.
BOr, BOr,
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
/// The bitwise XOR (binary ~) operator. /// The bitwise XOR (binary ~) operator.
BXor, BXor,
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
/// The bitwise NOT (unary ~) operator. /// The bitwise NOT (unary ~) operator.
BNot, BNot,
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
/// The bitwise left shift (<<) operator. /// The bitwise left shift (<<) operator.
Shl, Shl,
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
/// The bitwise right shift (>>) operator. /// The bitwise right shift (>>) operator.
Shr, Shr,
/// The string concatenation operator `..`. /// The string concatenation operator `..`.
@ -75,7 +75,7 @@ pub enum MetaMethod {
/// ///
/// This is not an operator, but will be called by methods such as `tostring` and `print`. /// This is not an operator, but will be called by methods such as `tostring` and `print`.
ToString, ToString,
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
/// The `__pairs` metamethod. /// The `__pairs` metamethod.
/// ///
/// This is not an operator, but it will be called by the built-in `pairs` function. /// This is not an operator, but it will be called by the built-in `pairs` function.
@ -92,19 +92,19 @@ impl MetaMethod {
MetaMethod::Mod => b"__mod", MetaMethod::Mod => b"__mod",
MetaMethod::Pow => b"__pow", MetaMethod::Pow => b"__pow",
MetaMethod::Unm => b"__unm", MetaMethod::Unm => b"__unm",
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
MetaMethod::IDiv => b"__idiv", MetaMethod::IDiv => b"__idiv",
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
MetaMethod::BAnd => b"__band", MetaMethod::BAnd => b"__band",
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
MetaMethod::BOr => b"__bor", MetaMethod::BOr => b"__bor",
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
MetaMethod::BXor => b"__bxor", MetaMethod::BXor => b"__bxor",
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
MetaMethod::BNot => b"__bnot", MetaMethod::BNot => b"__bnot",
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
MetaMethod::Shl => b"__shl", MetaMethod::Shl => b"__shl",
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
MetaMethod::Shr => b"__shr", MetaMethod::Shr => b"__shr",
MetaMethod::Concat => b"__concat", MetaMethod::Concat => b"__concat",
MetaMethod::Len => b"__len", MetaMethod::Len => b"__len",
@ -115,7 +115,7 @@ impl MetaMethod {
MetaMethod::NewIndex => b"__newindex", MetaMethod::NewIndex => b"__newindex",
MetaMethod::Call => b"__call", MetaMethod::Call => b"__call",
MetaMethod::ToString => b"__tostring", MetaMethod::ToString => b"__tostring",
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
MetaMethod::Pairs => b"__pairs", MetaMethod::Pairs => b"__pairs",
} }
} }
@ -387,18 +387,19 @@ impl<'lua> AnyUserData<'lua> {
/// Sets an associated value to this `AnyUserData`. /// Sets an associated value to this `AnyUserData`.
/// ///
/// The value may be any Lua value whatsoever, and can be retrieved with [`get_user_value`]. /// The value may be any Lua value whatsoever, and can be retrieved with [`get_user_value`].
/// As Lua < 5.3 allows to store only tables, the value will be stored in a table at index 1.
/// ///
/// [`get_user_value`]: #method.get_user_value /// [`get_user_value`]: #method.get_user_value
pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> { pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
let lua = self.0.lua; let lua = self.0.lua;
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
let v = { let v = {
// Lua 5.2/5.1 allows to store only table. Then we will wrap the value. // Lua 5.2/5.1 allows to store only a table. Then we will wrap the value.
let t = lua.create_table()?; let t = lua.create_table()?;
t.raw_set(1, v)?; t.raw_set(1, v)?;
crate::Value::Table(t) crate::Value::Table(t)
}; };
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
let v = v.to_lua(lua)?; let v = v.to_lua(lua)?;
unsafe { unsafe {
let _sg = StackGuard::new(lua.state); let _sg = StackGuard::new(lua.state);
@ -412,6 +413,8 @@ impl<'lua> AnyUserData<'lua> {
/// Returns an associated value set by [`set_user_value`]. /// Returns an associated value set by [`set_user_value`].
/// ///
/// For Lua < 5.3 the value will be automatically extracted from the table wrapper from index 1.
///
/// [`set_user_value`]: #method.set_user_value /// [`set_user_value`]: #method.set_user_value
pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> { pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
let lua = self.0.lua; let lua = self.0.lua;
@ -424,7 +427,7 @@ impl<'lua> AnyUserData<'lua> {
}; };
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
return crate::Table::from_lua(res, lua)?.get(1); return crate::Table::from_lua(res, lua)?.get(1);
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
V::from_lua(res, lua) V::from_lua(res, lua)
} }

View File

@ -485,7 +485,7 @@ pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
// Does not call lua_checkstack, uses 1 stack space. // Does not call lua_checkstack, uses 1 stack space.
pub unsafe fn get_main_state(state: *mut ffi::lua_State) -> *mut ffi::lua_State { pub unsafe fn get_main_state(state: *mut ffi::lua_State) -> *mut ffi::lua_State {
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
{ {
ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_MAINTHREAD); ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_MAINTHREAD);
let main_state = ffi::lua_tothread(state, -1); let main_state = ffi::lua_tothread(state, -1);

View File

@ -7,7 +7,7 @@ fn test_gc_control() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();
let globals = lua.globals(); let globals = lua.globals();
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
{ {
assert!(lua.gc_is_running()); assert!(lua.gc_is_running());
lua.gc_stop(); lua.gc_stop();

View File

@ -389,7 +389,7 @@ fn test_num_conversion() -> Result<()> {
assert_eq!(lua.load("1.0").eval::<i64>()?, 1); assert_eq!(lua.load("1.0").eval::<i64>()?, 1);
assert_eq!(lua.load("1.0").eval::<f64>()?, 1.0); assert_eq!(lua.load("1.0").eval::<f64>()?, 1.0);
#[cfg(feature = "lua53")] #[cfg(any(feature = "lua54", feature = "lua53"))]
assert_eq!(lua.load("1.0").eval::<String>()?, "1.0"); 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"))]
assert_eq!(lua.load("1.0").eval::<String>()?, "1"); assert_eq!(lua.load("1.0").eval::<String>()?, "1");
@ -466,7 +466,12 @@ fn test_pcall_xpcall() -> Result<()> {
assert_eq!(globals.get::<_, String>("pcall_error")?, "testerror"); assert_eq!(globals.get::<_, String>("pcall_error")?, "testerror");
assert_eq!(globals.get::<_, bool>("xpcall_statusr")?, false); assert_eq!(globals.get::<_, bool>("xpcall_statusr")?, false);
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luajit"))] #[cfg(any(
feature = "lua54",
feature = "lua53",
feature = "lua52",
feature = "luajit"
))]
assert_eq!( assert_eq!(
globals.get::<_, std::string::String>("xpcall_error")?, globals.get::<_, std::string::String>("xpcall_error")?,
"testerror" "testerror"
@ -799,7 +804,7 @@ fn context_thread() -> Result<()> {
) )
.into_function()?; .into_function()?;
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
f.call::<_, ()>(lua.current_thread())?; f.call::<_, ()>(lua.current_thread())?;
#[cfg(any(feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua51", feature = "luajit"))]

View File

@ -100,7 +100,12 @@ fn coroutine_from_closure() -> Result<()> {
let thrd_main = lua.create_function(|_, ()| Ok(()))?; let thrd_main = lua.create_function(|_, ()| Ok(()))?;
lua.globals().set("main", thrd_main)?; lua.globals().set("main", thrd_main)?;
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luajit"))] #[cfg(any(
feature = "lua54",
feature = "lua53",
feature = "lua52",
feature = "luajit"
))]
let thrd: Thread = lua.load("coroutine.create(main)").eval()?; let thrd: Thread = lua.load("coroutine.create(main)").eval()?;
#[cfg(feature = "lua51")] #[cfg(feature = "lua51")]
let thrd: Thread = lua let thrd: Thread = lua

View File

@ -95,7 +95,7 @@ fn test_metamethods() -> Result<()> {
Err("no such custom index".to_lua_err()) Err("no such custom index".to_lua_err())
} }
}); });
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
methods.add_meta_method(MetaMethod::Pairs, |lua, data, ()| { methods.add_meta_method(MetaMethod::Pairs, |lua, data, ()| {
use std::iter::FromIterator; use std::iter::FromIterator;
let stateless_iter = lua.create_function(|_, (data, i): (MyUserData, i64)| { let stateless_iter = lua.create_function(|_, (data, i): (MyUserData, i64)| {
@ -120,7 +120,7 @@ fn test_metamethods() -> Result<()> {
10 10
); );
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
let pairs_it = { let pairs_it = {
lua.load( lua.load(
r#" r#"
@ -140,7 +140,7 @@ fn test_metamethods() -> Result<()> {
assert_eq!(lua.load("userdata1 - userdata2").eval::<MyUserData>()?.0, 4); assert_eq!(lua.load("userdata1 - userdata2").eval::<MyUserData>()?.0, 4);
assert_eq!(lua.load("userdata1:get()").eval::<i64>()?, 7); assert_eq!(lua.load("userdata1:get()").eval::<i64>()?, 7);
assert_eq!(lua.load("userdata2.inner").eval::<i64>()?, 3); assert_eq!(lua.load("userdata2.inner").eval::<i64>()?, 3);
#[cfg(any(feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
assert_eq!(pairs_it.call::<_, i64>(())?, 28); assert_eq!(pairs_it.call::<_, i64>(())?, 28);
assert!(lua.load("userdata2.nonexist_field").eval::<()>().is_err()); assert!(lua.load("userdata2.nonexist_field").eval::<()>().is_err());