code_executor/
compiler.rs1use std::{
2 fs,
3 io::Write,
4 path::PathBuf,
5 process::{Command, Stdio},
6};
7
8use crate::{CommandArgs, Error, Result, util};
9
10#[derive(Debug, Clone, Copy)]
11pub struct Compiler<'a> {
12 pub main_file: &'a str,
13 pub args: Option<CommandArgs<'a>>,
14}
15
16impl Compiler<'_> {
17 #[tracing::instrument(err)]
18 fn create_project(&self, code: &str) -> Result<PathBuf> {
19 let project_path = util::generate_unique_path(code);
20
21 fs::create_dir_all(&project_path)?;
22
23 let mut main_file_path = project_path.clone();
24 main_file_path.push(self.main_file);
25
26 let mut main_file = fs::OpenOptions::new()
27 .create_new(true)
28 .write(true)
29 .open(&main_file_path)?;
30
31 main_file.write_all(code.as_bytes())?;
32
33 Ok(project_path)
34 }
35
36 #[tracing::instrument(err)]
37 pub fn compile(&self, code: &str) -> Result<PathBuf> {
38 let project_path = self.create_project(code)?;
39
40 let Some(CommandArgs {
41 binary: compiler,
42 args,
43 }) = self.args
44 else {
45 return Ok(project_path);
46 };
47
48 let process = Command::new(compiler)
49 .args(args)
50 .current_dir(&project_path)
51 .stderr(Stdio::piped())
52 .spawn()?;
53
54 let compilation_error = process.wait_with_output()?.stderr;
55
56 if !compilation_error.is_empty() {
57 return Err(Error::Compilation {
58 message: String::from_utf8(compilation_error)?,
59 });
60 }
61
62 Ok(project_path)
63 }
64}