use serde_json;
use serde_json::Value;
use std::fs;
use std::process::{Command, Stdio};
use std::io::prelude::*;
use serde::{Serialize, Deserialize};
#[derive(Debug)]
pub struct Input<'a> {
filename: &'a str,
input_file: String,
cmd_params: CmdParam,
}
#[derive(Debug)]
pub struct Runner {
stdout: String,
stderr: String,
}
pub trait Spawn {
fn run(&self) -> Runner;
fn run_compiled(&self) -> Runner;
fn run_interpreted(&self) -> Runner;
}
impl<'a> Spawn for Input<'a> {
fn run(&self) -> Runner {
let result: Runner;
if self.cmd_params.file_type == 1 {
result = Spawn::run_interpreted(self);
} else {
result = Spawn::run_compiled(self);
}
result
}
fn run_compiled(&self) -> Runner {
let filepath = self.filename;
let arg_vec = self.cmd_params.command.clone();
let mut new_arg: Vec<String> = Vec::new();
{
for index in 0..arg_vec.len() {
let arg = &arg_vec[index];
if arg == "file_path" {
new_arg.push(String::from("src/temp/") + self.filename.clone());
} else {
new_arg.push(arg.to_string());
}
}
}
let file_path = &(String::from("src/temp/") + &filepath + &self.cmd_params.lang_ext);
new_arg.push(file_path.to_string());
let compile = Command::new(self.cmd_params.default_path.clone())
.args(&new_arg)
.output()
.expect("fail to build");
let mut s = String::from("out");
if compile.stderr.len() == 0 {
let execute = match Command::new(&(String::from("src/temp/") + &filepath))
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn() {
Err(why) => panic!("couldn't spawn wc: {:?}", why),
Ok(process) => process,
};
match execute.stdin.unwrap().write_all(&fs::read(self.input_file.clone()).unwrap()) {
Err(why) => panic!("couldn't write to wc stdin: {:?}", why),
Ok(_) => println!("sent pangram to wc"),
}
s = String::new();
match execute.stdout.unwrap().read_to_string(&mut s) {
Err(why) => panic!("couldn't read wc stdout: {:?}",why),
Ok(_) => (),
}
}
match cleanup_file(filepath, &self.cmd_params.lang_ext, self.cmd_params.file_type) {
Ok(_) => (),
Err(e) => panic!("Hey {:?}", e),
};
Runner {
stdout: s,
stderr: String::from("err"),
}
}
fn run_interpreted(&self) -> Runner {
let filepath = self.filename;
println!("{}", filepath);
let execute = match Command::new(self.cmd_params.default_path.clone())
.arg(String::from("src/temp/") + &filepath + &self.cmd_params.lang_ext)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn() {
Err(why) => panic!("couldn't spawn wc: {:?}", why),
Ok(process) => process,
};
match execute.stdin.unwrap().write_all(&fs::read(self.input_file.clone()).unwrap()) {
Err(why) => panic!("couldn't write to wc stdin: {:?}", why),
Ok(_) => println!("sent pangram to wc"),
}
let mut s = String::new();
match execute.stdout.unwrap().read_to_string(&mut s) {
Err(why) => panic!("couldn't read wc stdout: {:?}",why),
Ok(_) => (),
}
match cleanup_file(filepath, &self.cmd_params.lang_ext, self.cmd_params.file_type) {
Ok(_) => (),
Err(e) => panic!("Hey {:?}", e),
};
Runner {
stdout: s,
stderr: String::from("err"),
}
}
}
#[derive(Debug)]
pub struct ClientReq<'r> {
code_file: Vec<u8>,
file_type: &'r str,
input_file: Vec<Vec<u8>>,
}
pub fn create_spawn(req: ClientReq) {
file_runner_command(req.file_type);
}
#[warn(dead_code)]
fn save_to_temp(file: Vec<u8>, name: String) {
match fs::write(name, file) {
Ok(_) => (),
Err(e) => panic!(e),
}
}
#[derive(Serialize, Deserialize, Debug)]
struct CmdParam {
command: Vec<String>,
default_path: String,
#[serde(rename = "type")]
file_type: u8,
lang_ext: String,
}
#[warn(dead_code)]
fn file_runner_command(ext: &str) -> CmdParam {
let json_cont = match fs::read_to_string("config/lang.json") {
Ok(v) => v,
Err(e) => panic!("JSON FILE:: {:?}", e),
};
let data: Value = serde_json::from_str(&json_cont[..]).unwrap();
let data1 = data.get(ext).unwrap();
let params: CmdParam = serde_json::from_value(data1.clone()).unwrap();
params
}
fn cleanup_file(filepath: &str, extension: &str, file_type: u8) -> std::io::Result<()> {
if file_type == 1 {
fs::remove_file(String::from("src/temp/") + &filepath + extension)?;
} else {
fs::remove_file(String::from("src/temp/") + &filepath)?;
fs::remove_file(String::from("src/temp/") + &filepath + extension)?;
}
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
use std::fs;
use uuid::Uuid;
#[test]
fn py_run() {
let cont = fs::read("src/temp/hello.py").unwrap();
let filename: String = Uuid::new_v4().to_string();
let ext: &str = "py2";
let cmd_params: CmdParam = file_runner_command(ext);
let input_filename = String::from("src/temp/input.in");
save_to_temp(
cont,
String::from("src/temp/") + &filename.clone() + &cmd_params.lang_ext,
);
let input: &Input = &Input {
filename: &filename,
cmd_params: cmd_params,
input_file: input_filename,
};
let result: Runner = Spawn::run(input);
println!("hey {:?}", result);
}
#[test]
fn c_run() {
let cont = fs::read("src/temp/hello.c").unwrap();
let filename: String = Uuid::new_v4().to_string();
let ext: &str = "c";
let cmd_params: CmdParam = file_runner_command(ext);
let input_filename = String::from("src/temp/input.in");
save_to_temp(
cont,
String::from("src/temp/") + &filename.clone() + &cmd_params.lang_ext,
);
let input: &Input = &Input {
filename: &filename,
cmd_params: cmd_params,
input_file: input_filename,
};
let result: Runner = Spawn::run(input);
println!("hey {:?}", result);
}
#[test]
fn go_run() {
}
}