use std::{io::Write, process::Stdio};
use crate::common::runtime::InputData;
use super::CodeRuntime;
#[derive(Debug, Clone)]
pub struct NativeRuntime;
#[derive(Debug, Clone)]
pub struct NativeConfig {
pub stdin: InputData,
}
impl Default for NativeConfig {
fn default() -> Self {
Self {
stdin: InputData::Ignore,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct NativeAdditionalData {
pub program: Option<String>,
}
impl CodeRuntime for NativeRuntime {
type Config = NativeConfig;
type AdditionalData = NativeAdditionalData;
type Error = std::io::Error;
fn run(
&self,
code: &crate::compilers::CompiledCode<Self>,
config: Self::Config,
) -> Result<super::ExecutionResult, Self::Error> {
let mut process = match &code.additional_data.program {
Some(program) => {
let mut cmd = std::process::Command::new(program);
cmd.arg(code.executable.as_ref().unwrap());
cmd
}
None => std::process::Command::new(code.executable.as_ref().unwrap()),
};
match config.stdin {
InputData::Ignore => {
process.stdin(std::process::Stdio::null());
}
_ => {
process.stdin(Stdio::piped());
}
};
process.stdout(Stdio::piped());
process.stderr(Stdio::piped());
let mut process = process.spawn()?;
let start_time = std::time::Instant::now();
match config.stdin {
InputData::Ignore => {}
InputData::String(data) => {
process.stdin.as_mut().unwrap().write_all(data.as_bytes())?;
}
InputData::File(path) => {
let mut file = std::fs::File::open(path)?;
std::io::copy(&mut file, process.stdin.as_mut().unwrap())?;
}
};
let output = process.wait_with_output()?;
let time_taken = start_time.elapsed();
let stdout = match output.stdout.len() {
0 => None,
_ => Some(String::from_utf8(output.stdout).unwrap()),
};
let stderr = match output.stderr.len() {
0 => None,
_ => Some(String::from_utf8(output.stderr).unwrap()),
};
Ok(super::ExecutionResult {
stdout,
stderr,
time_taken,
exit_code: output.status.code().unwrap_or(0),
})
}
}
#[cfg(test)]
mod tests {
use crate::compilers::{rust_compiler::RustCompiler, Compiler};
use super::*;
#[test]
fn test_native_runtime() {
let code = r#"
fn main() {
println!("Hello, world!");
}
"#;
let compiled_code = RustCompiler
.compile(&mut code.as_bytes(), Default::default())
.unwrap();
let result = NativeRuntime
.run(&compiled_code, Default::default())
.unwrap();
assert_eq!(result.stdout, Some("Hello, world!\n".to_owned()));
}
}