code_executor/
compiler.rs

1use 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    fn create_project(&self, code: &str) -> Result<PathBuf> {
18        let project_path = util::generate_unique_path(code);
19
20        fs::create_dir_all(&project_path)?;
21
22        let mut main_file_path = project_path.clone();
23        main_file_path.push(self.main_file);
24
25        let mut main_file = fs::OpenOptions::new()
26            .create_new(true)
27            .write(true)
28            .open(&main_file_path)?;
29
30        main_file.write_all(code.as_bytes())?;
31
32        Ok(project_path)
33    }
34
35    pub fn compile(&self, code: &str) -> Result<PathBuf> {
36        let project_path = self.create_project(code)?;
37
38        let Some(CommandArgs {
39            binary: compiler,
40            args,
41        }) = self.args
42        else {
43            return Ok(project_path);
44        };
45
46        let process = Command::new(compiler)
47            .args(args)
48            .current_dir(&project_path)
49            .stderr(Stdio::piped())
50            .spawn()?;
51
52        let compilation_error = process.wait_with_output()?.stderr;
53
54        if !compilation_error.is_empty() {
55            return Err(Error::Compilation {
56                message: String::from_utf8(compilation_error)?,
57            });
58        }
59
60        Ok(project_path)
61    }
62}