mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c85616137a | |||
| f52d106a82 | |||
| 10826a7e67 | |||
| 18c3255c90 | |||
| 6190427f37 | |||
| 9a5a341e44 | |||
| dd91ebfbe5 | |||
| f9fe869b76 | |||
| 6e4033abba | |||
| c213a85ef0 | |||
| 4963cc1b8b | |||
| 418e8fba32 | |||
| 08a7e30820 | |||
| 19676bda40 | |||
| 5a06778fbc | |||
| e33bdddc7a | |||
| cfb5d3fd45 | |||
| 84a174c94d | |||
| 888b2bbf8d |
@@ -1,3 +1,19 @@
|
||||
## v0.7.4
|
||||
|
||||
- Improved `Lua::create_registry_value` to reuse previously expired registry keys.
|
||||
No need to call `Lua::expire_registry_values` when creating/dropping registry values.
|
||||
- Added `Lua::replace_registry_value` to change value of an existing Registry Key
|
||||
- Async calls optimization
|
||||
|
||||
## v0.7.3
|
||||
|
||||
- Fixed cross-compilation issue (introduced in 84a174c)
|
||||
|
||||
## v0.7.2
|
||||
|
||||
- Allow `pkg-config` to omit include paths if they equals to standard (#114).
|
||||
- Various bugfixes (eg. #121)
|
||||
|
||||
## v0.7.1
|
||||
|
||||
- Fixed traceback generation for errors (#112)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua"
|
||||
version = "0.7.1" # remember to update html_root_url and mlua_derive
|
||||
version = "0.7.4" # remember to update html_root_url and mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@chucklefish.org>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/khvzak/mlua"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
`mlua` is bindings to [Lua](https://www.lua.org) programming language for Rust with a goal to provide
|
||||
_safe_ (as far as it's possible), high level, easy to use, practical and flexible API.
|
||||
|
||||
Started as [rlua] fork, `mlua` supports Lua 5.4, 5.3, 5.2 and 5.1 including LuaJIT (2.0.5 and 2.1 beta) and allows to write native Lua modules in Rust as well as use Lua in a standalone mode.
|
||||
Started as `rlua` fork, `mlua` supports Lua 5.4, 5.3, 5.2 and 5.1 including LuaJIT (2.0.5 and 2.1 beta) and allows to write native Lua modules in Rust as well as use Lua in a standalone mode.
|
||||
|
||||
`mlua` tested on Windows/macOS/Linux including module mode in [GitHub Actions] on `x86_64` platform and cross-compilation to `aarch64` (other targets are also supported).
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn probe_lua() -> PathBuf {
|
||||
pub fn probe_lua() -> Option<PathBuf> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
+23
-51
@@ -10,7 +10,7 @@ fn get_env_var(name: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn probe_lua() -> PathBuf {
|
||||
pub fn probe_lua() -> Option<PathBuf> {
|
||||
let include_dir = get_env_var("LUA_INC");
|
||||
let lib_dir = get_env_var("LUA_LIB");
|
||||
let lua_lib = get_env_var("LUA_LIB_NAME");
|
||||
@@ -38,73 +38,42 @@ pub fn probe_lua() -> PathBuf {
|
||||
println!("cargo:rustc-link-search=native={}", lib_dir);
|
||||
println!("cargo:rustc-link-lib={}{}", link_lib, lua_lib);
|
||||
}
|
||||
return PathBuf::from(include_dir);
|
||||
return Some(PathBuf::from(include_dir));
|
||||
}
|
||||
|
||||
// Find using `pkg-config`
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
{
|
||||
let mut lua = pkg_config::Config::new()
|
||||
.range_version((Bound::Included("5.4"), Bound::Excluded("5.5")))
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua");
|
||||
|
||||
if lua.is_err() {
|
||||
lua = pkg_config::Config::new()
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua5.4");
|
||||
}
|
||||
|
||||
lua.unwrap().include_paths[0].clone()
|
||||
}
|
||||
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.4", "5.5", "lua5.4", "5.4");
|
||||
#[cfg(feature = "lua53")]
|
||||
{
|
||||
let mut lua = pkg_config::Config::new()
|
||||
.range_version((Bound::Included("5.3"), Bound::Excluded("5.4")))
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua");
|
||||
|
||||
if lua.is_err() {
|
||||
lua = pkg_config::Config::new()
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua5.3");
|
||||
}
|
||||
|
||||
lua.unwrap().include_paths[0].clone()
|
||||
}
|
||||
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.3", "5.4", "lua5.3", "5.3");
|
||||
#[cfg(feature = "lua52")]
|
||||
{
|
||||
let mut lua = pkg_config::Config::new()
|
||||
.range_version((Bound::Included("5.2"), Bound::Excluded("5.3")))
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua");
|
||||
|
||||
if lua.is_err() {
|
||||
lua = pkg_config::Config::new()
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua5.2");
|
||||
}
|
||||
|
||||
lua.unwrap().include_paths[0].clone()
|
||||
}
|
||||
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.2", "5.3", "lua5.2", "5.2");
|
||||
#[cfg(feature = "lua51")]
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.1", "5.2", "lua5.1", "5.1");
|
||||
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "lua51"
|
||||
))]
|
||||
{
|
||||
let mut lua = pkg_config::Config::new()
|
||||
.range_version((Bound::Included("5.1"), Bound::Excluded("5.2")))
|
||||
.range_version((Bound::Included(incl_bound), Bound::Excluded(excl_bound)))
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua");
|
||||
|
||||
if lua.is_err() {
|
||||
lua = pkg_config::Config::new()
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua5.1");
|
||||
.probe(alt_probe);
|
||||
}
|
||||
|
||||
lua.unwrap().include_paths[0].clone()
|
||||
lua.expect(&format!("cannot find Lua {} using `pkg-config`", ver))
|
||||
.include_paths
|
||||
.get(0)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
#[cfg(feature = "luajit")]
|
||||
@@ -114,6 +83,9 @@ pub fn probe_lua() -> PathBuf {
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("luajit");
|
||||
|
||||
lua.unwrap().include_paths[0].clone()
|
||||
lua.expect("cannot find LuaJIT using `pkg-config`")
|
||||
.include_paths
|
||||
.get(0)
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn probe_lua() -> PathBuf {
|
||||
pub fn probe_lua() -> Option<PathBuf> {
|
||||
#[cfg(feature = "lua54")]
|
||||
let artifacts = lua_src::Build::new().build(lua_src::Lua54);
|
||||
#[cfg(feature = "lua53")]
|
||||
@@ -21,5 +21,5 @@ pub fn probe_lua() -> PathBuf {
|
||||
#[cfg(not(feature = "module"))]
|
||||
artifacts.print_cargo_metadata();
|
||||
|
||||
artifacts.include_dir().to_owned()
|
||||
Some(artifacts.include_dir().to_owned())
|
||||
}
|
||||
|
||||
+7
-3
@@ -68,11 +68,14 @@ impl CommandExt for Command {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_glue<P: AsRef<Path> + std::fmt::Debug>(include_path: &P) {
|
||||
// `include_path` is optional as Lua headers can be also found in compiler standard paths
|
||||
fn build_glue(include_path: Option<impl AsRef<Path>>) {
|
||||
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
|
||||
let mut config = cc::Build::new();
|
||||
config.include(include_path);
|
||||
if let Some(include_path) = include_path {
|
||||
config.include(include_path.as_ref());
|
||||
}
|
||||
|
||||
// Compile and run glue.c
|
||||
let glue = build_dir.join("glue");
|
||||
@@ -245,9 +248,10 @@ fn main() {
|
||||
|
||||
let include_dir = find::probe_lua();
|
||||
if env::var("TARGET").unwrap() != env::var("HOST").unwrap() {
|
||||
// The `probe_lua` call above is still needed here
|
||||
generate_glue().unwrap();
|
||||
} else {
|
||||
build_glue(&include_dir);
|
||||
build_glue(include_dir);
|
||||
println!("cargo:rerun-if-changed=src/ffi/glue/glue.c");
|
||||
}
|
||||
|
||||
|
||||
@@ -175,8 +175,7 @@ impl Tokens {
|
||||
pub(crate) fn retokenize(tt: TokenStream) -> Tokens {
|
||||
Tokens(
|
||||
tt.into_iter()
|
||||
.map(Tokens::from)
|
||||
.flatten()
|
||||
.flat_map(Tokens::from)
|
||||
.peekable()
|
||||
.batching(|iter| {
|
||||
// Find variable tokens
|
||||
@@ -217,7 +216,7 @@ impl From<TokenTree> for Tokens {
|
||||
|
||||
vec![Token::new_delim(b, tt.clone(), true)]
|
||||
.into_iter()
|
||||
.chain(g.stream().into_iter().map(Tokens::from).flatten())
|
||||
.chain(g.stream().into_iter().flat_map(Tokens::from))
|
||||
.chain(vec![Token::new_delim(e, tt, false)])
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -101,6 +101,10 @@ pub const LUA_TFUNCTION: c_int = 6;
|
||||
pub const LUA_TUSERDATA: c_int = 7;
|
||||
pub const LUA_TTHREAD: c_int = 8;
|
||||
|
||||
// Type produced by LuaJIT FFI module
|
||||
#[cfg(feature = "luajit")]
|
||||
pub const LUA_TCDATA: c_int = 10;
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
pub const LUA_NUMTYPES: c_int = 9;
|
||||
#[cfg(any(feature = "lua53", feature = "lua52"))]
|
||||
|
||||
@@ -236,6 +236,9 @@ pub use self::lua::LUA_ERRGCMM;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
pub use self::lua::{LUA_ENVIRONINDEX, LUA_GLOBALSINDEX};
|
||||
|
||||
#[cfg(feature = "luajit")]
|
||||
pub use self::lua::LUA_TCDATA;
|
||||
|
||||
// constants from lauxlib.h
|
||||
pub use self::lauxlib::{LUA_ERRFILE, LUA_NOREF, LUA_REFNIL};
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@
|
||||
//! [`serde::Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
|
||||
|
||||
// mlua types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/mlua/0.7.1")]
|
||||
#![doc(html_root_url = "https://docs.rs/mlua/0.7.4")]
|
||||
// Deny warnings inside doc tests / examples. When this isn't present, rustdoc doesn't show *any*
|
||||
// warnings at all.
|
||||
#![doc(test(attr(deny(warnings))))]
|
||||
|
||||
+97
-18
@@ -83,7 +83,7 @@ struct ExtraData {
|
||||
app_data: RefCell<HashMap<TypeId, Box<dyn Any + Send>>>,
|
||||
|
||||
libs: StdLib,
|
||||
mem_info: Option<Box<MemoryInfo>>,
|
||||
mem_info: Option<ptr::NonNull<MemoryInfo>>,
|
||||
safe: bool, // Same as in the Lua struct
|
||||
|
||||
ref_thread: *mut ffi::lua_State,
|
||||
@@ -180,6 +180,7 @@ impl LuaOptions {
|
||||
/// Sets [`catch_rust_panics`] option.
|
||||
///
|
||||
/// [`catch_rust_panics`]: #structfield.catch_rust_panics
|
||||
#[must_use]
|
||||
pub const fn catch_rust_panics(mut self, enabled: bool) -> Self {
|
||||
self.catch_rust_panics = enabled;
|
||||
self
|
||||
@@ -190,6 +191,7 @@ impl LuaOptions {
|
||||
/// [`thread_cache_size`]: #structfield.thread_cache_size
|
||||
#[cfg(feature = "async")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||
#[must_use]
|
||||
pub const fn thread_cache_size(mut self, size: usize) -> Self {
|
||||
self.thread_cache_size = size;
|
||||
self
|
||||
@@ -242,6 +244,9 @@ impl Drop for Lua {
|
||||
impl Drop for ExtraData {
|
||||
fn drop(&mut self) {
|
||||
*mlua_expect!(self.registry_unref_list.lock(), "unref list poisoned") = None;
|
||||
if let Some(mem_info) = self.mem_info {
|
||||
drop(unsafe { Box::from_raw(mem_info.as_ptr()) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,13 +391,13 @@ impl Lua {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
let mut mem_info = Box::new(MemoryInfo {
|
||||
let mem_info = Box::into_raw(Box::new(MemoryInfo {
|
||||
used_memory: 0,
|
||||
memory_limit: 0,
|
||||
});
|
||||
}));
|
||||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
let state = ffi::lua_newstate(allocator, &mut *mem_info as *mut MemoryInfo as *mut c_void);
|
||||
let state = ffi::lua_newstate(allocator, mem_info as *mut c_void);
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
let state = ffi::luaL_newstate();
|
||||
|
||||
@@ -406,7 +411,7 @@ impl Lua {
|
||||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
{
|
||||
extra.mem_info = Some(mem_info);
|
||||
extra.mem_info = ptr::NonNull::new(mem_info);
|
||||
}
|
||||
|
||||
mlua_expect!(
|
||||
@@ -918,7 +923,7 @@ impl Lua {
|
||||
pub fn used_memory(&self) -> usize {
|
||||
unsafe {
|
||||
let state = self.main_state.unwrap_or(self.state);
|
||||
match &(*self.extra.get()).mem_info {
|
||||
match (*self.extra.get()).mem_info.map(|x| x.as_ref()) {
|
||||
Some(mem_info) => mem_info.used_memory as usize,
|
||||
None => {
|
||||
// Get data from the Lua GC
|
||||
@@ -942,7 +947,7 @@ impl Lua {
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
pub fn set_memory_limit(&self, memory_limit: usize) -> Result<usize> {
|
||||
unsafe {
|
||||
match &mut (*self.extra.get()).mem_info {
|
||||
match (*self.extra.get()).mem_info.map(|mut x| x.as_mut()) {
|
||||
Some(mem_info) => {
|
||||
let prev_limit = mem_info.memory_limit as usize;
|
||||
mem_info.memory_limit = memory_limit as isize;
|
||||
@@ -1703,11 +1708,12 @@ impl Lua {
|
||||
|
||||
/// Place a value in the Lua registry with an auto-generated key.
|
||||
///
|
||||
/// This value will be available to rust from all `Lua` instances which share the same main
|
||||
/// This value will be available to Rust from all `Lua` instances which share the same main
|
||||
/// state.
|
||||
///
|
||||
/// Be warned, garbage collection of values held inside the registry is not automatic, see
|
||||
/// [`RegistryKey`] for more details.
|
||||
/// However, dropped [`RegistryKey`]s automatically reused to store new values.
|
||||
///
|
||||
/// [`RegistryKey`]: crate::RegistryKey
|
||||
pub fn create_registry_value<'lua, T: ToLua<'lua>>(&'lua self, t: T) -> Result<RegistryKey> {
|
||||
@@ -1716,14 +1722,29 @@ impl Lua {
|
||||
let _sg = StackGuard::new(self.state);
|
||||
check_stack(self.state, 4)?;
|
||||
|
||||
let unref_list = (*self.extra.get()).registry_unref_list.clone();
|
||||
self.push_value(t)?;
|
||||
|
||||
// Try to reuse previously allocated RegistryKey
|
||||
let unref_list2 = unref_list.clone();
|
||||
let mut unref_list2 = mlua_expect!(unref_list2.lock(), "unref list poisoned");
|
||||
if let Some(registry_id) = unref_list2.as_mut().and_then(|x| x.pop()) {
|
||||
// It must be safe to replace the value without triggering memory error
|
||||
ffi::lua_rawseti(self.state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
|
||||
return Ok(RegistryKey {
|
||||
registry_id,
|
||||
unref_list,
|
||||
});
|
||||
}
|
||||
|
||||
// Allocate a new RegistryKey
|
||||
let registry_id = protect_lua!(self.state, 1, 0, |state| {
|
||||
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
|
||||
})?;
|
||||
|
||||
Ok(RegistryKey {
|
||||
registry_id,
|
||||
unref_list: (*self.extra.get()).registry_unref_list.clone(),
|
||||
unref_list,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1772,6 +1793,37 @@ impl Lua {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Replaces a value in the Lua registry by its `RegistryKey`.
|
||||
///
|
||||
/// See [`create_registry_value`] for more details.
|
||||
///
|
||||
/// [`create_registry_value`]: #method.create_registry_value
|
||||
pub fn replace_registry_value<'lua, T: ToLua<'lua>>(
|
||||
&'lua self,
|
||||
key: &RegistryKey,
|
||||
t: T,
|
||||
) -> Result<()> {
|
||||
if !self.owns_registry_value(key) {
|
||||
return Err(Error::MismatchedRegistryKey);
|
||||
}
|
||||
|
||||
let t = t.to_lua(self)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(self.state);
|
||||
check_stack(self.state, 2)?;
|
||||
|
||||
self.push_value(t)?;
|
||||
// It must be safe to replace the value without triggering memory error
|
||||
ffi::lua_rawseti(
|
||||
self.state,
|
||||
ffi::LUA_REGISTRYINDEX,
|
||||
key.registry_id as Integer,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the given `RegistryKey` was created by a `Lua` which shares the underlying
|
||||
/// main state with this `Lua` instance.
|
||||
///
|
||||
@@ -1983,6 +2035,13 @@ impl Lua {
|
||||
|
||||
ffi::LUA_TTHREAD => Value::Thread(Thread(self.pop_ref())),
|
||||
|
||||
#[cfg(feature = "luajit")]
|
||||
ffi::LUA_TCDATA => {
|
||||
ffi::lua_pop(state, 1);
|
||||
// TODO: Fix this in a next major release
|
||||
panic!("cdata objects cannot be handled by mlua yet");
|
||||
}
|
||||
|
||||
_ => mlua_panic!("LUA_TNONE in pop_value"),
|
||||
}
|
||||
}
|
||||
@@ -2278,6 +2337,22 @@ impl Lua {
|
||||
}
|
||||
}
|
||||
|
||||
struct StateGuard(*mut Lua, *mut ffi::lua_State);
|
||||
|
||||
impl StateGuard {
|
||||
unsafe fn new(lua: *mut Lua, state: *mut ffi::lua_State) -> Self {
|
||||
let orig_state = (*lua).state;
|
||||
(*lua).state = state;
|
||||
Self(lua, orig_state)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for StateGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe { (*self.0).state = self.1 }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int {
|
||||
let extra = match ffi::lua_type(state, ffi::lua_upvalueindex(1)) {
|
||||
ffi::LUA_TUSERDATA => {
|
||||
@@ -2299,7 +2374,7 @@ impl Lua {
|
||||
}
|
||||
|
||||
let lua = &mut (*upvalue).lua;
|
||||
lua.state = state;
|
||||
let _guard = StateGuard::new(lua, state);
|
||||
|
||||
let mut args = MultiValue::new_or_cached(lua);
|
||||
args.reserve(nargs as usize);
|
||||
@@ -2379,19 +2454,23 @@ impl Lua {
|
||||
Function(self.pop_ref())
|
||||
};
|
||||
|
||||
unsafe extern "C" fn unpack(state: *mut ffi::lua_State) -> c_int {
|
||||
let len = ffi::lua_tointeger(state, 2);
|
||||
ffi::luaL_checkstack(state, len as c_int, ptr::null());
|
||||
for i in 1..=len {
|
||||
ffi::lua_rawgeti(state, 1, i);
|
||||
}
|
||||
len as c_int
|
||||
}
|
||||
|
||||
let coroutine = self.globals().get::<_, Table>("coroutine")?;
|
||||
|
||||
let env = self.create_table_with_capacity(0, 4)?;
|
||||
env.set("get_poll", get_poll)?;
|
||||
env.set("yield", coroutine.get::<_, Function>("yield")?)?;
|
||||
env.set(
|
||||
"unpack",
|
||||
self.create_function(|lua, (tbl, len): (Table, Integer)| {
|
||||
let mut values = MultiValue::new_or_cached(lua);
|
||||
values.refill(tbl.raw_sequence_values_by_len(Some(len)))?;
|
||||
Ok(values)
|
||||
})?,
|
||||
)?;
|
||||
unsafe {
|
||||
env.set("unpack", self.create_c_function(unpack)?)?;
|
||||
}
|
||||
env.set("pending", {
|
||||
LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut c_void)
|
||||
})?;
|
||||
|
||||
@@ -61,6 +61,7 @@ impl Options {
|
||||
/// Sets [`deny_unsupported_types`] option.
|
||||
///
|
||||
/// [`deny_unsupported_types`]: #structfield.deny_unsupported_types
|
||||
#[must_use]
|
||||
pub const fn deny_unsupported_types(mut self, enabled: bool) -> Self {
|
||||
self.deny_unsupported_types = enabled;
|
||||
self
|
||||
@@ -69,6 +70,7 @@ impl Options {
|
||||
/// Sets [`deny_recursive_tables`] option.
|
||||
///
|
||||
/// [`deny_recursive_tables`]: #structfield.deny_recursive_tables
|
||||
#[must_use]
|
||||
pub fn deny_recursive_tables(mut self, enabled: bool) -> Self {
|
||||
self.deny_recursive_tables = enabled;
|
||||
self
|
||||
|
||||
@@ -69,6 +69,7 @@ impl Options {
|
||||
/// Sets [`set_array_metatable`] option.
|
||||
///
|
||||
/// [`set_array_metatable`]: #structfield.set_array_metatable
|
||||
#[must_use]
|
||||
pub const fn set_array_metatable(mut self, enabled: bool) -> Self {
|
||||
self.set_array_metatable = enabled;
|
||||
self
|
||||
@@ -77,6 +78,7 @@ impl Options {
|
||||
/// Sets [`serialize_none_to_null`] option.
|
||||
///
|
||||
/// [`serialize_none_to_null`]: #structfield.serialize_none_to_null
|
||||
#[must_use]
|
||||
pub const fn serialize_none_to_null(mut self, enabled: bool) -> Self {
|
||||
self.serialize_none_to_null = enabled;
|
||||
self
|
||||
@@ -85,6 +87,7 @@ impl Options {
|
||||
/// Sets [`serialize_unit_to_null`] option.
|
||||
///
|
||||
/// [`serialize_unit_to_null`]: #structfield.serialize_unit_to_null
|
||||
#[must_use]
|
||||
pub const fn serialize_unit_to_null(mut self, enabled: bool) -> Self {
|
||||
self.serialize_unit_to_null = enabled;
|
||||
self
|
||||
|
||||
+1
-1
@@ -455,7 +455,7 @@ impl<'lua> Table<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "async", feature = "serialize"))]
|
||||
#[cfg(any(feature = "serialize"))]
|
||||
pub(crate) fn raw_sequence_values_by_len<V: FromLua<'lua>>(
|
||||
self,
|
||||
len: Option<Integer>,
|
||||
|
||||
@@ -800,6 +800,17 @@ fn test_drop_registry_value() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_registry_value() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let key = lua.create_registry_value::<i32>(42)?;
|
||||
lua.replace_registry_value(&key, "new value")?;
|
||||
assert_eq!(lua.registry_value::<String>(&key)?, "new value");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lua_registry_hash() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
@@ -1256,3 +1267,24 @@ fn test_warnings() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "luajit")]
|
||||
#[should_panic]
|
||||
fn test_luajit_cdata() {
|
||||
let lua = unsafe { Lua::unsafe_new() };
|
||||
let _v: Result<Value> = lua
|
||||
.load(
|
||||
r#"
|
||||
local ffi = require("ffi")
|
||||
ffi.cdef[[
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
]]
|
||||
local ptr = ffi.C.malloc(1)
|
||||
ffi.C.free(ptr)
|
||||
return ptr
|
||||
"#,
|
||||
)
|
||||
.eval();
|
||||
}
|
||||
|
||||
+9
-1
@@ -130,7 +130,15 @@ fn test_thread_reset() -> Result<()> {
|
||||
assert_eq!(thread.status(), ThreadStatus::Error);
|
||||
assert_eq!(Arc::strong_count(&arc), 2);
|
||||
assert!(thread.reset(func.clone()).is_err());
|
||||
assert_eq!(thread.status(), ThreadStatus::Error);
|
||||
// Reset behavior has changed in Lua v5.4.4
|
||||
// It's became possible to force reset thread by popping error object
|
||||
assert!(matches!(
|
||||
thread.status(),
|
||||
ThreadStatus::Unresumable | ThreadStatus::Error
|
||||
));
|
||||
// Would pass in 5.4.4
|
||||
// assert!(thread.reset(func.clone()).is_ok());
|
||||
// assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user