code_executor/runner/
mod.rs1mod metrics;
2
3use std::{
4 fs,
5 io::Write,
6 path::{Path, PathBuf},
7 process::{Command, Stdio},
8};
9
10pub use metrics::*;
11
12use crate::{
13 CommandArgs, Error, Result, runner,
14 sandbox::{self, Sandbox},
15 util,
16};
17
18#[derive(Debug)]
19pub struct Runner<'a> {
20 pub main_file: &'a str,
21 pub compiler_args: Option<CommandArgs<'a>>,
22 pub sandbox_config: sandbox::Config<'a>,
23}
24
25impl Runner<'_> {
26 fn create_unique_project(&self, code: &str) -> Result<PathBuf> {
27 let project_path = util::generate_unique_path(code);
28
29 fs::create_dir_all(&project_path)?;
30
31 let mut main_file_path = project_path.clone();
32 main_file_path.push(self.main_file);
33
34 let mut main_file = fs::OpenOptions::new()
35 .create_new(true)
36 .write(true)
37 .open(&main_file_path)?;
38
39 main_file.write_all(code.as_bytes())?;
40
41 Ok(project_path)
42 }
43
44 fn compile(&self, project_path: &Path) -> Result<()> {
46 let Some(CommandArgs {
47 binary: compiler,
48 args,
49 }) = self.compiler_args
50 else {
51 return Ok(());
52 };
53
54 let process = Command::new(compiler)
55 .args(args)
56 .current_dir(project_path)
57 .stderr(Stdio::piped())
58 .spawn()?;
59
60 let compilation_error = process.wait_with_output()?.stderr;
61
62 if !compilation_error.is_empty() {
63 return Err(Error::Compilation {
64 message: String::from_utf8(compilation_error)?,
65 });
66 }
67
68 Ok(())
69 }
70
71 pub fn run(
72 &self,
73 code: impl AsRef<str>,
74 input_path: impl AsRef<Path>,
75 ) -> Result<runner::metrics::Metrics> {
76 let project_path = self.create_unique_project(code.as_ref())?;
77 let output_path =
78 project_path.join(util::hash((input_path.as_ref(), "output")).to_string());
79 let error_path = project_path.join(util::hash((input_path.as_ref(), "error")).to_string());
80
81 self.compile(&project_path)?;
82
83 let sandbox = Sandbox::builder()
84 .project_path(project_path)
85 .config(self.sandbox_config.clone())
86 .input(input_path.as_ref())?
87 .output_path(&output_path)
88 .error_path(&error_path)
89 .build();
90
91 let sandbox = sandbox.spawn()?;
92 let result = sandbox.wait()?;
93
94 Ok(result)
95 }
96}