code_runner 0.1.0

A Code Runner written in Rust which takes code in any language executes them and then returns output to the method calling
Documentation
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");
        // println!("Hey {:?}", compile.stderr);
        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() {

    }
}