use crate::lang_runner::runner::Language;
use crate::utils::file_utils;
use crate::utils::program_utils::ExecutionLimits;
use std::path::Path;
use super::language_name::LanguageName;
use super::runner_error_types::RunnerErrorType;
#[derive(Debug)]
pub struct ProgramStore {
correct_file: Language,
test_file: Language,
}
#[derive(Debug)]
enum FileType {
Correct,
Test,
}
impl ProgramStore {
pub fn new(
correct_file: &Path,
test_file: &Path,
do_force_compile: bool,
) -> Result<Self, Box<RunnerErrorType>> {
Ok(ProgramStore {
correct_file: Language::new(correct_file, do_force_compile)?,
test_file: Language::new(test_file, do_force_compile)?,
})
}
pub fn new_with_limits(
correct_file: &Path,
test_file: &Path,
do_force_compile: bool,
execution_limits: ExecutionLimits,
) -> Result<Self, Box<RunnerErrorType>> {
Ok(ProgramStore {
correct_file: Language::new_with_limits(
correct_file,
do_force_compile,
execution_limits,
)?,
test_file: Language::new_with_limits(test_file, do_force_compile, execution_limits)?,
})
}
pub fn new_from_custom_dest(
correct_file: &Path,
test_file: &Path,
correct_dest: Option<&Path>,
test_dest: Option<&Path>,
do_force_compile: bool,
) -> Result<Self, Box<RunnerErrorType>> {
Ok(ProgramStore {
correct_file: Language::new_from_custom_dest(
correct_file,
correct_dest,
do_force_compile,
)?,
test_file: Language::new_from_custom_dest(test_file, test_dest, do_force_compile)?,
})
}
pub fn new_from_custom_dest_with_limits(
correct_file: &Path,
test_file: &Path,
correct_dest: Option<&Path>,
test_dest: Option<&Path>,
do_force_compile: bool,
execution_limits: ExecutionLimits,
) -> Result<Self, Box<RunnerErrorType>> {
Ok(ProgramStore {
correct_file: Language::new_from_custom_dest_with_limits(
correct_file,
correct_dest,
do_force_compile,
execution_limits,
)?,
test_file: Language::new_from_custom_dest_with_limits(
test_file,
test_dest,
do_force_compile,
execution_limits,
)?,
})
}
pub fn new_from_text(
correct_text: &str,
test_text: &str,
correct_lang: LanguageName,
test_lang: LanguageName,
do_force_compile: bool,
) -> Result<Self, Box<RunnerErrorType>> {
Ok(ProgramStore {
correct_file: Language::new_from_text(correct_text, correct_lang, do_force_compile)?,
test_file: Language::new_from_text(test_text, test_lang, do_force_compile)?,
})
}
pub fn new_from_text_with_limits(
correct_text: &str,
test_text: &str,
correct_lang: LanguageName,
test_lang: LanguageName,
do_force_compile: bool,
execution_limits: ExecutionLimits,
) -> Result<Self, Box<RunnerErrorType>> {
Ok(ProgramStore {
correct_file: Language::new_from_text_with_limits(
correct_text,
correct_lang,
do_force_compile,
execution_limits,
)?,
test_file: Language::new_from_text_with_limits(
test_text,
test_lang,
do_force_compile,
execution_limits,
)?,
})
}
pub fn new_from_language(
correct_lang: Language,
test_lang: Language,
) -> Result<Self, Box<RunnerErrorType>> {
Ok(ProgramStore {
correct_file: correct_lang,
test_file: test_lang,
})
}
pub fn run_codes_and_compare_output(
&self,
stdin_content: &str,
) -> Result<(bool, String, String), Box<RunnerErrorType>> {
let correct_output =
self.run_program_code_interface(&self.correct_file, stdin_content, FileType::Correct)?;
let test_output =
self.run_program_code_interface(&self.test_file, stdin_content, FileType::Test)?;
Ok((
!file_utils::string_diff(&correct_output, &test_output),
correct_output,
test_output,
))
}
fn run_program_code_interface(
&self,
language: &Language,
stdin_content: &str,
file_type: FileType,
) -> Result<String, Box<RunnerErrorType>> {
language
.run_program_code(stdin_content)
.map_err(move |err| {
eprintln!("[PROGRAM STORE ERROR] Failed to run {file_type:?}!\n{err}");
err
})
}
}