mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f2d48ce296 | |||
| 0fa39d431d | |||
| 0aa86c4d47 | |||
| ea2faa3755 | |||
| 59c9abbac7 | |||
| 8f3de8aa19 | |||
| 317ce7caa6 | |||
| 3a44729a48 | |||
| 3d46fad459 | |||
| ffc4bd599c | |||
| 1c969da286 | |||
| 45fd2fa40a |
@@ -1,3 +1,9 @@
|
||||
## v0.9.8
|
||||
|
||||
- Fixed serializing same table multiple times (#408)
|
||||
- Use `mlua-sys` v0.6 (to support Luau 0.624+)
|
||||
- Fixed cross compilation of windows dlls from unix (#394)
|
||||
|
||||
## v0.9.7
|
||||
|
||||
- Implemented `IntoLua` for `RegistryKey`
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua"
|
||||
version = "0.9.7" # remember to update mlua_derive
|
||||
version = "0.9.8" # remember to update mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@kyju.org>"]
|
||||
rust-version = "1.71"
|
||||
edition = "2021"
|
||||
@@ -44,7 +44,7 @@ macros = ["mlua_derive/macros"]
|
||||
unstable = []
|
||||
|
||||
[dependencies]
|
||||
mlua_derive = { version = "=0.9.2", optional = true, path = "mlua_derive" }
|
||||
mlua_derive = { version = "=0.9.3", optional = true, path = "mlua_derive" }
|
||||
bstr = { version = "1.0", features = ["std"], default_features = false }
|
||||
once_cell = { version = "1.0" }
|
||||
num-traits = { version = "0.2.14" }
|
||||
@@ -55,7 +55,7 @@ erased-serde = { version = "0.4", optional = true }
|
||||
serde-value = { version = "0.7", optional = true }
|
||||
parking_lot = { version = "0.12", optional = true }
|
||||
|
||||
ffi = { package = "mlua-sys", version = "0.5.1", path = "mlua-sys" }
|
||||
ffi = { package = "mlua-sys", version = "0.6.0", path = "mlua-sys" }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libloading = { version = "0.8", optional = true }
|
||||
|
||||
@@ -133,7 +133,7 @@ Add to `Cargo.toml` :
|
||||
|
||||
``` toml
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["lua54", "vendored"] }
|
||||
mlua = { version = "0.9.8", features = ["lua54", "vendored"] }
|
||||
```
|
||||
|
||||
`main.rs`
|
||||
@@ -168,7 +168,7 @@ Add to `Cargo.toml` :
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["lua54", "module"] }
|
||||
mlua = { version = "0.9.8", features = ["lua54", "module"] }
|
||||
```
|
||||
|
||||
`lib.rs` :
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua-sys"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>"]
|
||||
rust-version = "1.71"
|
||||
edition = "2021"
|
||||
@@ -40,4 +40,4 @@ cfg-if = "1.0"
|
||||
pkg-config = "0.3.17"
|
||||
lua-src = { version = ">= 546.0.2, < 546.1.0", optional = true }
|
||||
luajit-src = { version = ">= 210.5.0, < 210.6.0", optional = true }
|
||||
luau0-src = { version = "0.8.0", optional = true }
|
||||
luau0-src = { version = "0.9.0", optional = true }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::env;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(feature = "luau", feature = "vendored"))] {
|
||||
#[path = "find_vendored.rs"]
|
||||
@@ -17,8 +19,8 @@ fn main() {
|
||||
|
||||
println!("cargo:rerun-if-changed=build");
|
||||
|
||||
#[cfg(windows)]
|
||||
if cfg!(feature = "module") {
|
||||
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
if target_os == "windows" && cfg!(feature = "module") {
|
||||
if !std::env::var("LUA_LIB_NAME").unwrap_or_default().is_empty() {
|
||||
// Don't use raw-dylib linking
|
||||
find::probe_lua();
|
||||
|
||||
@@ -525,6 +525,7 @@ pub struct lua_Debug {
|
||||
//
|
||||
|
||||
#[repr(C)]
|
||||
#[non_exhaustive]
|
||||
pub struct lua_Callbacks {
|
||||
/// arbitrary userdata pointer that is never overwritten by Luau
|
||||
pub userdata: *mut c_void,
|
||||
@@ -552,3 +553,8 @@ pub struct lua_Callbacks {
|
||||
extern "C" {
|
||||
pub fn lua_callbacks(L: *mut lua_State) -> *mut lua_Callbacks;
|
||||
}
|
||||
|
||||
// Functions from customization lib
|
||||
extern "C" {
|
||||
pub fn luau_setfflag(name: *const c_char, value: c_int) -> c_int;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
//! Contains definitions from `luacode.h`.
|
||||
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::slice;
|
||||
use std::{ptr, slice};
|
||||
|
||||
#[repr(C)]
|
||||
#[non_exhaustive]
|
||||
pub struct lua_CompileOptions {
|
||||
pub optimizationLevel: c_int,
|
||||
pub debugLevel: c_int,
|
||||
pub typeInfoLevel: c_int,
|
||||
pub coverageLevel: c_int,
|
||||
pub vectorLib: *const c_char,
|
||||
pub vectorCtor: *const c_char,
|
||||
@@ -14,6 +16,21 @@ pub struct lua_CompileOptions {
|
||||
pub mutableGlobals: *const *const c_char,
|
||||
}
|
||||
|
||||
impl Default for lua_CompileOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
optimizationLevel: 1,
|
||||
debugLevel: 1,
|
||||
typeInfoLevel: 0,
|
||||
coverageLevel: 0,
|
||||
vectorLib: ptr::null(),
|
||||
vectorCtor: ptr::null(),
|
||||
vectorType: ptr::null(),
|
||||
mutableGlobals: ptr::null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C-unwind" {
|
||||
#[link_name = "luau_compile"]
|
||||
pub fn luau_compile_(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua_derive"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>"]
|
||||
edition = "2021"
|
||||
description = "Procedural macros for the mlua crate."
|
||||
|
||||
@@ -58,13 +58,13 @@ pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
};
|
||||
|
||||
let wrapped = quote! {
|
||||
::mlua::require_module_feature!();
|
||||
mlua::require_module_feature!();
|
||||
|
||||
#func
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C-unwind" fn #ext_entrypoint_name(state: *mut ::mlua::lua_State) -> ::std::os::raw::c_int {
|
||||
let lua = ::mlua::Lua::init_from_ptr(state);
|
||||
unsafe extern "C-unwind" fn #ext_entrypoint_name(state: *mut mlua::lua_State) -> ::std::os::raw::c_int {
|
||||
let lua = mlua::Lua::init_from_ptr(state);
|
||||
#skip_memory_check
|
||||
lua.entrypoint1(state, #func_name)
|
||||
}
|
||||
@@ -95,7 +95,7 @@ pub fn chunk(input: TokenStream) -> TokenStream {
|
||||
});
|
||||
|
||||
let wrapped_code = quote! {{
|
||||
use ::mlua::{AsChunk, ChunkMode, Lua, Result, Table};
|
||||
use mlua::{AsChunk, ChunkMode, Lua, Result, Table};
|
||||
use ::std::borrow::Cow;
|
||||
use ::std::cell::Cell;
|
||||
use ::std::io::Result as IoResult;
|
||||
|
||||
+21
-9
@@ -122,6 +122,7 @@ pub enum ChunkMode {
|
||||
pub struct Compiler {
|
||||
optimization_level: u8,
|
||||
debug_level: u8,
|
||||
type_info_level: u8,
|
||||
coverage_level: u8,
|
||||
vector_lib: Option<String>,
|
||||
vector_ctor: Option<String>,
|
||||
@@ -144,6 +145,7 @@ impl Compiler {
|
||||
Compiler {
|
||||
optimization_level: 1,
|
||||
debug_level: 1,
|
||||
type_info_level: 0,
|
||||
coverage_level: 0,
|
||||
vector_lib: None,
|
||||
vector_ctor: None,
|
||||
@@ -176,6 +178,16 @@ impl Compiler {
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets Luau type information level used to guide native code generation decisions.
|
||||
///
|
||||
/// Possible values:
|
||||
/// * 0 - generate for native modules (default)
|
||||
/// * 1 - generate for all modules
|
||||
pub const fn set_type_info_level(mut self, level: u8) -> Self {
|
||||
self.type_info_level = level;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets Luau compiler code coverage level.
|
||||
///
|
||||
/// Possible values:
|
||||
@@ -250,15 +262,15 @@ impl Compiler {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let options = ffi::lua_CompileOptions {
|
||||
optimizationLevel: self.optimization_level as c_int,
|
||||
debugLevel: self.debug_level as c_int,
|
||||
coverageLevel: self.coverage_level as c_int,
|
||||
vectorLib: vector_lib.map_or(ptr::null(), |s| s.as_ptr()),
|
||||
vectorCtor: vector_ctor.map_or(ptr::null(), |s| s.as_ptr()),
|
||||
vectorType: vector_type.map_or(ptr::null(), |s| s.as_ptr()),
|
||||
mutableGlobals: mutable_globals_ptr,
|
||||
};
|
||||
let mut options = ffi::lua_CompileOptions::default();
|
||||
options.optimizationLevel = self.optimization_level as c_int;
|
||||
options.debugLevel = self.debug_level as c_int;
|
||||
options.typeInfoLevel = self.type_info_level as c_int;
|
||||
options.coverageLevel = self.coverage_level as c_int;
|
||||
options.vectorLib = vector_lib.map_or(ptr::null(), |s| s.as_ptr());
|
||||
options.vectorCtor = vector_ctor.map_or(ptr::null(), |s| s.as_ptr());
|
||||
options.vectorType = vector_type.map_or(ptr::null(), |s| s.as_ptr());
|
||||
options.mutableGlobals = mutable_globals_ptr;
|
||||
ffi::luau_compile(source.as_ref(), options)
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -1288,6 +1288,21 @@ impl Lua {
|
||||
unsafe { (*self.extra.get()).enable_jit = enable };
|
||||
}
|
||||
|
||||
/// Sets Luau feature flag (global setting).
|
||||
///
|
||||
/// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
|
||||
#[cfg(feature = "luau")]
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::result_unit_err)]
|
||||
pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
|
||||
if let Ok(name) = CString::new(name) {
|
||||
if unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 } {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Err(())
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
||||
+2
-2
@@ -660,14 +660,14 @@ impl<'lua, 'de> de::VariantAccess<'de> for VariantDeserializer<'lua> {
|
||||
|
||||
// Adds `ptr` to the `visited` map and removes on drop
|
||||
// Used to track recursive tables but allow to traverse same tables multiple times
|
||||
struct RecursionGuard {
|
||||
pub(crate) struct RecursionGuard {
|
||||
ptr: *const c_void,
|
||||
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
|
||||
}
|
||||
|
||||
impl RecursionGuard {
|
||||
#[inline]
|
||||
fn new(table: &Table, visited: &Rc<RefCell<FxHashSet<*const c_void>>>) -> Self {
|
||||
pub(crate) fn new(table: &Table, visited: &Rc<RefCell<FxHashSet<*const c_void>>>) -> Self {
|
||||
let visited = Rc::clone(visited);
|
||||
let ptr = table.to_pointer();
|
||||
visited.borrow_mut().insert(ptr);
|
||||
|
||||
+5
-5
@@ -1089,7 +1089,7 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use crate::serde::de::{check_value_for_skip, MapPairs};
|
||||
use crate::serde::de::{check_value_for_skip, MapPairs, RecursionGuard};
|
||||
use crate::value::SerializableValue;
|
||||
|
||||
let convert_result = |res: Result<()>, serialize_err: Option<S::Error>| match res {
|
||||
@@ -1101,7 +1101,7 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
|
||||
|
||||
let options = self.options;
|
||||
let visited = &self.visited;
|
||||
visited.borrow_mut().insert(self.table.to_pointer());
|
||||
let _guard = RecursionGuard::new(self.table, visited);
|
||||
|
||||
// Array
|
||||
let len = self.table.raw_len();
|
||||
@@ -1109,7 +1109,7 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
|
||||
let mut seq = serializer.serialize_seq(Some(len))?;
|
||||
let mut serialize_err = None;
|
||||
let res = self.table.for_each_value::<Value>(|value| {
|
||||
let skip = check_value_for_skip(&value, self.options, &self.visited)
|
||||
let skip = check_value_for_skip(&value, self.options, visited)
|
||||
.map_err(|err| Error::SerializeError(err.to_string()))?;
|
||||
if skip {
|
||||
// continue iteration
|
||||
@@ -1129,9 +1129,9 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
let mut serialize_err = None;
|
||||
let mut process_pair = |key, value| {
|
||||
let skip_key = check_value_for_skip(&key, self.options, &self.visited)
|
||||
let skip_key = check_value_for_skip(&key, self.options, visited)
|
||||
.map_err(|err| Error::SerializeError(err.to_string()))?;
|
||||
let skip_value = check_value_for_skip(&value, self.options, &self.visited)
|
||||
let skip_value = check_value_for_skip(&value, self.options, visited)
|
||||
.map_err(|err| Error::SerializeError(err.to_string()))?;
|
||||
if skip_key || skip_value {
|
||||
// continue iteration
|
||||
|
||||
@@ -484,3 +484,9 @@ fn test_buffer() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fflags() {
|
||||
// We cannot really on any particular feature flag to be present
|
||||
assert!(Lua::set_fflag("UnknownFlag", true).is_err());
|
||||
}
|
||||
|
||||
@@ -269,6 +269,27 @@ fn test_serialize_globals() -> LuaResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_same_table_twice() -> LuaResult<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let value = lua
|
||||
.load(
|
||||
r#"
|
||||
local foo = {}
|
||||
return {
|
||||
a = foo,
|
||||
b = foo,
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.eval::<Value>()?;
|
||||
let json = serde_json::to_string(&value.to_serializable().sort_keys(true)).unwrap();
|
||||
assert_eq!(json, r#"{"a":{},"b":{}}"#);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_value_struct() -> LuaResult<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
Reference in New Issue
Block a user