mirror of
https://github.com/lune-org/lune.git
synced 2025-05-04 10:43:57 +01:00
122 lines
3.3 KiB
Rust
122 lines
3.3 KiB
Rust
#![allow(clippy::cargo_common_metadata)]
|
|
|
|
use std::{
|
|
env::consts::{ARCH, OS},
|
|
path::MAIN_SEPARATOR,
|
|
process::Stdio,
|
|
};
|
|
|
|
use mlua::prelude::*;
|
|
use mlua_luau_scheduler::Functions;
|
|
|
|
use lune_utils::{
|
|
path::get_current_dir,
|
|
process::{ProcessArgs, ProcessEnv},
|
|
TableBuilder,
|
|
};
|
|
|
|
mod create;
|
|
mod exec;
|
|
mod options;
|
|
|
|
use self::options::ProcessSpawnOptions;
|
|
|
|
const TYPEDEFS: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/types.d.luau"));
|
|
|
|
/**
|
|
Returns a string containing type definitions for the `process` standard library.
|
|
*/
|
|
#[must_use]
|
|
pub fn typedefs() -> String {
|
|
TYPEDEFS.to_string()
|
|
}
|
|
|
|
/**
|
|
Creates the `process` standard library module.
|
|
|
|
# Errors
|
|
|
|
Errors when out of memory.
|
|
*/
|
|
#[allow(clippy::missing_panics_doc)]
|
|
pub fn module(lua: Lua) -> LuaResult<LuaTable> {
|
|
let mut cwd_str = get_current_dir()
|
|
.to_str()
|
|
.expect("cwd should be valid UTF-8")
|
|
.to_string();
|
|
if !cwd_str.ends_with(MAIN_SEPARATOR) {
|
|
cwd_str.push(MAIN_SEPARATOR);
|
|
}
|
|
|
|
// Create constants for OS & processor architecture
|
|
let os = lua.create_string(OS.to_lowercase())?;
|
|
let arch = lua.create_string(ARCH.to_lowercase())?;
|
|
let endianness = lua.create_string(if cfg!(target_endian = "big") {
|
|
"big"
|
|
} else {
|
|
"little"
|
|
})?;
|
|
|
|
// Find the readonly args array
|
|
let args_vec = lua
|
|
.app_data_ref::<Vec<String>>()
|
|
.ok_or_else(|| LuaError::runtime("Missing args vec in Lua app data"))?
|
|
.clone();
|
|
|
|
// Create userdatas for args + env
|
|
// TODO: Move this up into the runtime creation instead,
|
|
// and set it as app data there to later fetch here
|
|
let process_args = ProcessArgs::from_iter(args_vec);
|
|
let process_env = ProcessEnv::current();
|
|
lua.set_app_data(process_args.clone());
|
|
lua.set_app_data(process_env.clone());
|
|
|
|
// Create our process exit function, the scheduler crate provides this
|
|
let fns = Functions::new(lua.clone())?;
|
|
let process_exit = fns.exit;
|
|
|
|
// Create the full process table
|
|
TableBuilder::new(lua)?
|
|
.with_value("os", os)?
|
|
.with_value("arch", arch)?
|
|
.with_value("endianness", endianness)?
|
|
.with_value("args", process_args)?
|
|
.with_value("cwd", cwd_str)?
|
|
.with_value("env", process_env)?
|
|
.with_value("exit", process_exit)?
|
|
.with_async_function("exec", process_exec)?
|
|
.with_function("create", process_create)?
|
|
.build_readonly()
|
|
}
|
|
|
|
async fn process_exec(
|
|
lua: Lua,
|
|
(program, args, mut options): (String, ProcessArgs, ProcessSpawnOptions),
|
|
) -> LuaResult<LuaTable> {
|
|
let stdin = options.stdio.stdin.take();
|
|
let stdout = options.stdio.stdout;
|
|
let stderr = options.stdio.stderr;
|
|
|
|
let child = options
|
|
.into_command(program, args)
|
|
.stdin(Stdio::piped())
|
|
.stdout(stdout.as_stdio())
|
|
.stderr(stderr.as_stdio())
|
|
.spawn()?;
|
|
|
|
exec::exec(lua, child, stdin, stdout, stderr).await
|
|
}
|
|
|
|
fn process_create(
|
|
lua: &Lua,
|
|
(program, args, options): (String, ProcessArgs, ProcessSpawnOptions),
|
|
) -> LuaResult<LuaValue> {
|
|
let child = options
|
|
.into_command(program, args)
|
|
.stdin(Stdio::piped())
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.spawn()?;
|
|
|
|
create::Child::new(lua, child).into_lua(lua)
|
|
}
|