mirror of
https://github.com/lune-org/lune.git
synced 2025-04-20 11:53:50 +01:00
refactor: polish a few things and clean up code
This commit is contained in:
parent
441a1eacfe
commit
2bf68c1e2a
2 changed files with 43 additions and 21 deletions
|
@ -1,8 +1,12 @@
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
process::ExitCode,
|
||||||
|
};
|
||||||
|
use tokio::{
|
||||||
|
fs::{self, OpenOptions},
|
||||||
|
io::AsyncWriteExt,
|
||||||
};
|
};
|
||||||
use tokio::fs;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use mlua::Compiler as LuaCompiler;
|
use mlua::Compiler as LuaCompiler;
|
||||||
|
@ -10,13 +14,13 @@ use mlua::Compiler as LuaCompiler;
|
||||||
pub async fn build_standalone<T: AsRef<Path> + Into<PathBuf>>(
|
pub async fn build_standalone<T: AsRef<Path> + Into<PathBuf>>(
|
||||||
output_path: T,
|
output_path: T,
|
||||||
code: impl AsRef<[u8]>,
|
code: impl AsRef<[u8]>,
|
||||||
) -> Result<()> {
|
) -> Result<ExitCode> {
|
||||||
// First, we read the contents of the lune interpreter as our starting point
|
// First, we read the contents of the lune interpreter as our starting point
|
||||||
let mut patched_bin = fs::read(env::current_exe()?).await?;
|
let mut patched_bin = fs::read(env::current_exe()?).await?;
|
||||||
let base_bin_offset = u64::try_from(patched_bin.len())?;
|
let base_bin_offset = u64::try_from(patched_bin.len())?;
|
||||||
|
|
||||||
// The signature which separates indicates the presence of bytecode to execute
|
// The signature which separates indicates the presence of bytecode to execute
|
||||||
// If a binary contains this signature, that must mean it is a standalone binar
|
// If a binary contains this signature, that must mean it is a standalone binary
|
||||||
let signature: Vec<u8> = vec![0x4f, 0x3e, 0xf8, 0x41, 0xc3, 0x3a, 0x52, 0x16];
|
let signature: Vec<u8> = vec![0x4f, 0x3e, 0xf8, 0x41, 0xc3, 0x3a, 0x52, 0x16];
|
||||||
|
|
||||||
// Compile luau input into bytecode
|
// Compile luau input into bytecode
|
||||||
|
@ -26,27 +30,28 @@ pub async fn build_standalone<T: AsRef<Path> + Into<PathBuf>>(
|
||||||
.set_debug_level(0)
|
.set_debug_level(0)
|
||||||
.compile(code);
|
.compile(code);
|
||||||
|
|
||||||
println!("{}", bytecode.len());
|
|
||||||
|
|
||||||
patched_bin.append(&mut bytecode.clone());
|
patched_bin.append(&mut bytecode.clone());
|
||||||
|
|
||||||
let mut meta = base_bin_offset.to_ne_bytes().to_vec();
|
let mut meta = base_bin_offset.to_ne_bytes().to_vec();
|
||||||
|
|
||||||
// bytecode base size files signature
|
// Include metadata in the META chunk, each field is 8 bytes
|
||||||
// meta.append(&mut [0, 0, 0, 0].to_vec()); // 4 extra padding bytes after 4 byte u64
|
meta.append(&mut (bytecode.len() as u64).to_ne_bytes().to_vec()); // Size of bytecode, used to calculate end offset at runtime
|
||||||
meta.append(&mut (bytecode.len() as u64).to_ne_bytes().to_vec()); // FIXME: len is greater than u8::max
|
|
||||||
meta.append(&mut 1_u64.to_ne_bytes().to_vec()); // Number of files, padded with null bytes
|
meta.append(&mut 1_u64.to_ne_bytes().to_vec()); // Number of files, padded with null bytes
|
||||||
// meta.append(&mut [0, 0, 0, 0].to_vec()); // 4 extra padding bytes after 4 byte u32
|
|
||||||
|
|
||||||
patched_bin.append(&mut meta);
|
patched_bin.append(&mut meta);
|
||||||
|
|
||||||
// Append the signature to the base binary
|
// Append the signature to the base binary
|
||||||
for byte in signature {
|
patched_bin.append(&mut signature.clone());
|
||||||
patched_bin.push(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the compiled binary to file
|
// Write the compiled binary to file
|
||||||
fs::write(output_path, patched_bin).await?;
|
OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.mode(0o770)
|
||||||
|
.open(output_path)
|
||||||
|
.await?
|
||||||
|
.write_all(&patched_bin)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(ExitCode::SUCCESS)
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,17 +155,26 @@ impl Cli {
|
||||||
|
|
||||||
// Read the current lune binary to memory
|
// Read the current lune binary to memory
|
||||||
let bin = read_to_vec(env::current_exe()?).await?;
|
let bin = read_to_vec(env::current_exe()?).await?;
|
||||||
// let mut bin = vec![0; tmp_bin.len() % signature.len()];
|
|
||||||
|
|
||||||
// println!("padding: {:?}", bin);
|
|
||||||
|
|
||||||
// bin.append(&mut tmp_bin);
|
|
||||||
|
|
||||||
let mut bytecode_offset = 0;
|
let mut bytecode_offset = 0;
|
||||||
let mut bytecode_size = 0;
|
let mut bytecode_size = 0;
|
||||||
|
|
||||||
// println!("{}",);
|
// standalone binary structure (reversed, 8 bytes per field)
|
||||||
|
// [0] => signature
|
||||||
|
// ----------------
|
||||||
|
// -- META Chunk --
|
||||||
|
// [1] => file count
|
||||||
|
// [2] => bytecode size
|
||||||
|
// [3] => bytecode offset
|
||||||
|
// ----------------
|
||||||
|
// -- MISC Chunk --
|
||||||
|
// [4..n] => bytecode (variable size)
|
||||||
|
// ----------------
|
||||||
|
// NOTE: All integers are 8 byte unsigned 64 bit (u64's).
|
||||||
|
|
||||||
|
// The rchunks will have unequally sized sections in the beginning
|
||||||
|
// but that doesn't matter to us because we don't need anything past the
|
||||||
|
// middle chunks where the bytecode is stored
|
||||||
for (idx, chunk) in bin.rchunks(signature.len()).enumerate() {
|
for (idx, chunk) in bin.rchunks(signature.len()).enumerate() {
|
||||||
if idx == 0 && chunk != signature {
|
if idx == 0 && chunk != signature {
|
||||||
// We don't have a standalone binary
|
// We don't have a standalone binary
|
||||||
|
@ -181,7 +190,13 @@ impl Cli {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we were able to retrieve the required metadata, we load
|
||||||
|
// and execute the bytecode
|
||||||
if bytecode_offset != 0 && bytecode_size != 0 {
|
if bytecode_offset != 0 && bytecode_size != 0 {
|
||||||
|
// FIXME: Passing arguments does not work like it should, because the first
|
||||||
|
// argument provided is treated as the script path. We should probably also not
|
||||||
|
// allow any runner functionality within standalone binaries
|
||||||
|
|
||||||
let result = Lune::new()
|
let result = Lune::new()
|
||||||
.with_args(self.script_args.clone())
|
.with_args(self.script_args.clone())
|
||||||
.run(
|
.run(
|
||||||
|
@ -200,6 +215,8 @@ impl Cli {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If not in a standalone context and we don't have any arguments
|
||||||
|
// display the interactive REPL interface
|
||||||
return repl::show_interface().await;
|
return repl::show_interface().await;
|
||||||
}
|
}
|
||||||
// Figure out if we should read from stdin or from a file,
|
// Figure out if we should read from stdin or from a file,
|
||||||
|
@ -232,7 +249,7 @@ impl Cli {
|
||||||
|
|
||||||
return Ok(
|
return Ok(
|
||||||
match build_standalone(output_path, strip_shebang(script_contents.clone())).await {
|
match build_standalone(output_path, strip_shebang(script_contents.clone())).await {
|
||||||
Ok(()) => ExitCode::SUCCESS,
|
Ok(exitcode) => exitcode,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{err}");
|
eprintln!("{err}");
|
||||||
ExitCode::FAILURE
|
ExitCode::FAILURE
|
||||||
|
|
Loading…
Add table
Reference in a new issue