From 2864cc9a6d9e12fabbf661b1ed9000ce88ddb31c Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Sun, 31 Dec 2023 21:20:33 +0800 Subject: [PATCH 1/4] add some compile methods --- .gitignore | 2 + src/chunk.rs | 2 +- src/lua.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++ tests/chunk.rs | 30 +++++++++++++ tests/scripts/a.lua | 1 + tests/scripts/b.lua | 1 + 6 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/scripts/a.lua create mode 100644 tests/scripts/b.lua diff --git a/.gitignore b/.gitignore index fcfec84e..fb2add4b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ Cargo.lock .vscode/ .DS_Store .stignore + +*.bin \ No newline at end of file diff --git a/src/chunk.rs b/src/chunk.rs index f3db5de2..0c380176 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -524,4 +524,4 @@ impl<'lua, 'a> Chunk<'lua, 'a> { buf.extend(source); buf } -} +} \ No newline at end of file diff --git a/src/lua.rs b/src/lua.rs index 13c348c0..4dc5a1c8 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -3192,6 +3192,111 @@ impl Lua { pub(crate) fn clone(&self) -> Arc { Arc::clone(&self.0) } + + /// Compile all the files to bytecode under a directory, save as `*.bin` + /// It designs for build script, so there will be no error return. + /// It will automatically print cargo:rerun-if-changed=* + /// + /// # Examples + /// + /// ``` + /// use mlua::prelude::*; + /// fn main(){ + /// let lua = Lua::new(); + /// + /// lua.compile_single("./a.lua") + /// .compile_single("./b.lua"); + /// } + /// ``` + #[cfg(not(feature = "luau"))] + #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))] + #[track_caller] + #[inline] + pub fn compile_single(&self, path: &str) -> &Self { + use std::fs; + use std::path::PathBuf; + + println!("cargo:rerun-if-changed={}", path); + + let bytes = fs::read(path).unwrap(); + + let strip; + #[cfg(debug_assertions)] + { + strip = true; + } + #[cfg(not(debug_assertions))] + { + strip = false; + } + + let bytecode = self.load(&bytes).into_function().unwrap().dump(strip); + + let mut path = PathBuf::from(path); + path.set_extension("bin"); + + fs::write(path, bytecode).unwrap(); + + self + } + + /// Compile all the files to bytecode under a directory, save as `*.bin` + /// It designs for build script, so there will be no error return. + /// It automatically print cargo:rerun-if-changed=* + /// + /// # Examples + /// + /// ``` + /// use mlua::prelude::*; + /// fn main(){ + /// let lua = Lua::new(); + /// + /// lua.compile_directory("./scripts") + /// compile_directory("./exetensions"); + /// } + /// ``` + #[cfg(not(feature = "luau"))] + #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))] + #[track_caller] + pub fn compile_directory(&self, path: &str) -> &Self { + use std::fs; + use std::string::String; + #[track_caller] + fn all_files(path: &str) -> std::io::Result> { + // here use a BFS to traversal all the files under a directory + let mut stk = vec![path.to_string()]; + let mut ans = Vec::new(); + while let Some(path) = stk.pop() { + for entry in fs::read_dir(path)? { + let entry = entry?; + let path = entry.path(); + let s = path + .to_str() + .unwrap_or_else(|| panic!("a path : {} is not UTF-8", path.display())) + .to_string(); + if path.is_dir() { + stk.push(s); + } else { + if let Some(exe)=path.extension(){ + if exe=="lua"{ + ans.push(s); + } + } + } + } + } + + Ok(ans) + } + + let files = all_files(path).expect("Fail to traversal the directory"); + + for path in files { + self.compile_single(path.as_str()); + } + + self + } } impl LuaInner { diff --git a/tests/chunk.rs b/tests/chunk.rs index 714e887b..3b10ec5f 100644 --- a/tests/chunk.rs +++ b/tests/chunk.rs @@ -28,6 +28,36 @@ fn test_chunk_path() -> Result<()> { Ok(()) } +#[test] +fn test_compile() { + let lua = Lua::new(); + + let assert = || { + assert_eq!( + lua.load(fs::read("./tests/scripts/a.bin").unwrap()) + .eval::() + .unwrap(), + "Helloworld".to_string() + ); + + assert_eq!( + lua.load(fs::read("./tests/scripts/b.bin").unwrap()) + .eval::() + .unwrap(), + "Helloworld".to_string() + ); + }; + + lua.compile_single("./tests/scripts/a.lua") + .compile_single("./tests/scripts/b.lua"); + + assert(); + + lua.compile_directory("./tests/scripts"); + + assert(); +} + #[test] #[cfg(feature = "macros")] fn test_chunk_macro() -> Result<()> { diff --git a/tests/scripts/a.lua b/tests/scripts/a.lua new file mode 100644 index 00000000..50aec14d --- /dev/null +++ b/tests/scripts/a.lua @@ -0,0 +1 @@ +return "Hello" .. "world" \ No newline at end of file diff --git a/tests/scripts/b.lua b/tests/scripts/b.lua new file mode 100644 index 00000000..50aec14d --- /dev/null +++ b/tests/scripts/b.lua @@ -0,0 +1 @@ +return "Hello" .. "world" \ No newline at end of file From 675db852201116e486dded0b17204c38873031b5 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Sun, 31 Dec 2023 21:34:22 +0800 Subject: [PATCH 2/4] fix docs --- src/lua.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/lua.rs b/src/lua.rs index 4dc5a1c8..4563a978 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -3194,8 +3194,12 @@ impl Lua { } /// Compile all the files to bytecode under a directory, save as `*.bin` + /// /// It designs for build script, so there will be no error return. + /// /// It will automatically print cargo:rerun-if-changed=* + /// + /// In release mode, it may not save all the debug information, see also [`Function::dump()`] /// /// # Examples /// @@ -3204,8 +3208,8 @@ impl Lua { /// fn main(){ /// let lua = Lua::new(); /// - /// lua.compile_single("./a.lua") - /// .compile_single("./b.lua"); + /// lua.compile_single("./tests/scripts/a.lua") + /// .compile_single("./tests/scripts/b.lua"); /// } /// ``` #[cfg(not(feature = "luau"))] @@ -3223,11 +3227,11 @@ impl Lua { let strip; #[cfg(debug_assertions)] { - strip = true; + strip = false; } #[cfg(not(debug_assertions))] { - strip = false; + strip = true; } let bytecode = self.load(&bytes).into_function().unwrap().dump(strip); @@ -3240,9 +3244,13 @@ impl Lua { self } - /// Compile all the files to bytecode under a directory, save as `*.bin` - /// It designs for build script, so there will be no error return. - /// It automatically print cargo:rerun-if-changed=* + /// Compile all the files with the extension `lua` to bytecode under a directory, save as `*.bin` + /// + /// It is designed for build script, so there will be no error return. + /// + /// It automatically print cargo:rerun-if-changed=* of each script file + /// + /// It calls [`Lua::compile_single()`] on every file /// /// # Examples /// @@ -3251,8 +3259,8 @@ impl Lua { /// fn main(){ /// let lua = Lua::new(); /// - /// lua.compile_directory("./scripts") - /// compile_directory("./exetensions"); + /// lua.compile_directory("./tests/scripts") + /// .compile_directory("./tests/scripts"); /// } /// ``` #[cfg(not(feature = "luau"))] From 81e042bc8a0e8d7354dfeee611368964c5ef7def Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Mon, 1 Jan 2024 09:04:15 +0800 Subject: [PATCH 3/4] 1. Better Panic Info 2. add feature conditon to tests, and manage test scripts better --- src/lua.rs | 74 ++++++++++++++++++---------- tests/chunk.rs | 36 ++++++++++++-- tests/scripts/{ => compile}/a.lua | 0 tests/scripts/{ => compile}/b.lua | 0 tests/scripts/compile/info.md | 1 + tests/scripts/multi_file_def/c.lua | 1 + tests/scripts/multi_file_def/d.lua | 1 + tests/scripts/multi_file_def/info.md | 1 + 8 files changed, 84 insertions(+), 30 deletions(-) rename tests/scripts/{ => compile}/a.lua (100%) rename tests/scripts/{ => compile}/b.lua (100%) create mode 100644 tests/scripts/compile/info.md create mode 100644 tests/scripts/multi_file_def/c.lua create mode 100644 tests/scripts/multi_file_def/d.lua create mode 100644 tests/scripts/multi_file_def/info.md diff --git a/src/lua.rs b/src/lua.rs index 4563a978..410a73a5 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -3194,11 +3194,11 @@ impl Lua { } /// Compile all the files to bytecode under a directory, save as `*.bin` - /// + /// /// It designs for build script, so there will be no error return. - /// + /// /// It will automatically print cargo:rerun-if-changed=* - /// + /// /// In release mode, it may not save all the debug information, see also [`Function::dump()`] /// /// # Examples @@ -3216,13 +3216,21 @@ impl Lua { #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))] #[track_caller] #[inline] - pub fn compile_single(&self, path: &str) -> &Self { + pub fn compile_single(&self, path: impl AsRef) -> &Self { use std::fs; use std::path::PathBuf; - println!("cargo:rerun-if-changed={}", path); + let path = path.as_ref(); - let bytes = fs::read(path).unwrap(); + println!("cargo:rerun-if-changed={}", path.display()); + + let bytes = fs::read(path).unwrap_or_else(|err| { + panic!( + "Error caused while reading the source file\nAt Path: {}\nCaused by:\n\t{:?}", + path.display(), + err + ) + }); let strip; #[cfg(debug_assertions)] @@ -3234,22 +3242,34 @@ impl Lua { strip = true; } - let bytecode = self.load(&bytes).into_function().unwrap().dump(strip); + let bytecode = self.load(&bytes).into_function().unwrap_or_else(|err|{ + panic!( + "Error caused while converting chunk into function\nAt Path: {}\nCaused by:\n\t{:?}", + path.display(), + err + ) + }).dump(strip); let mut path = PathBuf::from(path); path.set_extension("bin"); - fs::write(path, bytecode).unwrap(); + fs::write(&path, bytecode).unwrap_or_else(|err| { + panic!( + "Error caused while writing the bytecode\nAt Path: {}\nCaused by:\n\t{:?}", + path.display(), + err + ) + }); self } /// Compile all the files with the extension `lua` to bytecode under a directory, save as `*.bin` - /// + /// /// It is designed for build script, so there will be no error return. - /// + /// /// It automatically print cargo:rerun-if-changed=* of each script file - /// + /// /// It calls [`Lua::compile_single()`] on every file /// /// # Examples @@ -3266,28 +3286,24 @@ impl Lua { #[cfg(not(feature = "luau"))] #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))] #[track_caller] - pub fn compile_directory(&self, path: &str) -> &Self { + pub fn compile_directory(&self, path: impl AsRef) -> &Self { use std::fs; - use std::string::String; + use std::path::{Path, PathBuf}; #[track_caller] - fn all_files(path: &str) -> std::io::Result> { + fn all_files(path: impl AsRef) -> std::io::Result> { // here use a BFS to traversal all the files under a directory - let mut stk = vec![path.to_string()]; + let mut stk = vec![path.as_ref().to_path_buf()]; let mut ans = Vec::new(); while let Some(path) = stk.pop() { for entry in fs::read_dir(path)? { let entry = entry?; let path = entry.path(); - let s = path - .to_str() - .unwrap_or_else(|| panic!("a path : {} is not UTF-8", path.display())) - .to_string(); if path.is_dir() { - stk.push(s); + stk.push(path); } else { - if let Some(exe)=path.extension(){ - if exe=="lua"{ - ans.push(s); + if let Some(exe) = path.extension() { + if exe == "lua" { + ans.push(path); } } } @@ -3297,10 +3313,18 @@ impl Lua { Ok(ans) } - let files = all_files(path).expect("Fail to traversal the directory"); + let path = path.as_ref(); + + let files = all_files(path).unwrap_or_else(|err| { + panic!( + "Error caused while traversal the directory\nAt Path: {}\nCaused by:\n\t{:?}", + path.display(), + err + ) + }); for path in files { - self.compile_single(path.as_str()); + self.compile_single(path); } self diff --git a/tests/chunk.rs b/tests/chunk.rs index 3b10ec5f..4fc21912 100644 --- a/tests/chunk.rs +++ b/tests/chunk.rs @@ -5,6 +5,8 @@ use std::io; use mlua::{Lua, Result}; +use std::path::{Path, PathBuf}; + #[test] #[cfg(not(target_arch = "wasm32"))] fn test_chunk_path() -> Result<()> { @@ -29,35 +31,59 @@ fn test_chunk_path() -> Result<()> { } #[test] +#[cfg(not(feature = "luau"))] fn test_compile() { let lua = Lua::new(); + let work_dir = Path::new("./tests/scripts/compile/"); + let assert = || { assert_eq!( - lua.load(fs::read("./tests/scripts/a.bin").unwrap()) + lua.load(fs::read(work_dir.join("a.bin")).unwrap()) .eval::() .unwrap(), "Helloworld".to_string() ); assert_eq!( - lua.load(fs::read("./tests/scripts/b.bin").unwrap()) + lua.load(fs::read(work_dir.join("b.bin")).unwrap()) .eval::() .unwrap(), "Helloworld".to_string() ); }; - lua.compile_single("./tests/scripts/a.lua") - .compile_single("./tests/scripts/b.lua"); + lua.compile_single(work_dir.join("a.lua")) + .compile_single(work_dir.join("b.lua")); assert(); - lua.compile_directory("./tests/scripts"); + lua.compile_directory(work_dir); assert(); } +#[test] +#[cfg(not(feature = "luau"))] +fn multi_file_def() { + let lua = Lua::new(); + + let work_dir = Path::new("./tests/scripts/multi_file_def"); + + lua.compile_directory(work_dir); + + lua.load(fs::read(work_dir.join("c.bin")).unwrap()) + .exec() + .unwrap(); + + let value = lua + .load(fs::read(work_dir.join("d.bin")).unwrap()) + .eval::() + .unwrap(); + + assert_eq!(value.as_str(), "Hello world !"); +} + #[test] #[cfg(feature = "macros")] fn test_chunk_macro() -> Result<()> { diff --git a/tests/scripts/a.lua b/tests/scripts/compile/a.lua similarity index 100% rename from tests/scripts/a.lua rename to tests/scripts/compile/a.lua diff --git a/tests/scripts/b.lua b/tests/scripts/compile/b.lua similarity index 100% rename from tests/scripts/b.lua rename to tests/scripts/compile/b.lua diff --git a/tests/scripts/compile/info.md b/tests/scripts/compile/info.md new file mode 100644 index 00000000..da1b8d9b --- /dev/null +++ b/tests/scripts/compile/info.md @@ -0,0 +1 @@ +Belong to [test_compile()](../../chunk.rs) \ No newline at end of file diff --git a/tests/scripts/multi_file_def/c.lua b/tests/scripts/multi_file_def/c.lua new file mode 100644 index 00000000..2641bfbb --- /dev/null +++ b/tests/scripts/multi_file_def/c.lua @@ -0,0 +1 @@ +hello = "Hello world !" diff --git a/tests/scripts/multi_file_def/d.lua b/tests/scripts/multi_file_def/d.lua new file mode 100644 index 00000000..9aed7b7b --- /dev/null +++ b/tests/scripts/multi_file_def/d.lua @@ -0,0 +1 @@ +return hello; \ No newline at end of file diff --git a/tests/scripts/multi_file_def/info.md b/tests/scripts/multi_file_def/info.md new file mode 100644 index 00000000..640f505d --- /dev/null +++ b/tests/scripts/multi_file_def/info.md @@ -0,0 +1 @@ +Belong to [multi_file_def()](../../chunk.rs) \ No newline at end of file From f513f4c805ff763449fb3352af7980b6bb2cded1 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Mon, 1 Jan 2024 13:10:26 +0800 Subject: [PATCH 4/4] edit test --- tests/chunk.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/chunk.rs b/tests/chunk.rs index 4fc21912..55e37a79 100644 --- a/tests/chunk.rs +++ b/tests/chunk.rs @@ -58,6 +58,10 @@ fn test_compile() { assert(); + // remove them to make sure the code above don't influence them test below + fs::remove_file(work_dir.join("a.bin")).unwrap(); + fs::remove_file(work_dir.join("b.bin")).unwrap(); + lua.compile_directory(work_dir); assert();