noxue_compiler/lang.rs
1use serde::{Deserialize, Serialize};
2
3use crate::exec::{exec, Output};
4
5#[derive(Serialize, Deserialize)]
6struct RunTpl {
7 image: String, // docker iamge 名字
8 file: String, // 代码要保存的文件路径
9 prev_cmd: Option<String>, // 写入之前执行的命令,主要用于设置一些变量,给cmd中的命令使用
10 cmd: String, // 保存代码之后要执行的命令
11 timeout: i32, // 容器执行超时时间
12 memory: String, // 允许容器使用的内存,例如:20MB
13 cpuset: String, // 使用的cpu核心
14}
15
16/// 根据语言选择特定的执行模板来编译运行代码
17///
18/// ## 参数
19///
20/// * `tpl` - 指定的运行模板内容,使用模板更加方便扩展任意编程语言
21/// * `code` - 要编译的代码
22/// * `input` - 标准输入,用户给程序的输入数据
23///
24/// ## 模板格式:
25/// ```json
26/// {
27/// "image": "gcc", // 要使用那个docker imgage
28/// "file": "test.c", // 代码保存的文件名
29/// "cmd": "gcc test.c -o test\nif test -f \"./test\"; then\n./test\nfi", // 代码保存后要执行的命令
30/// "timeout": 10, // 超时时间,是从启动docker开始计算
31/// "memory": "20MB", // 允许占用的内存
32/// "cpuset":"0-3", // 使用的cpu核心
33/// }
34/// ```
35///
36/// ## 调用方式
37///
38/// ```
39/// use noxue_compiler::lang::run;
40/// fn main(){
41/// let code = r#"
42/// #include <stdio.h>
43///
44/// int main(){
45/// printf("hello");
46/// return 0;
47/// }"#;
48/// let tpl = r#"
49/// {
50/// "image": "gcc",
51/// "file": "test.c",
52/// "cmd": "gcc test.c -o test\nif test -f \"./test\"; then\n./test\nfi",
53/// "timeout": 10,
54/// "memory":"20MB",
55/// "cpuset":"0-3"
56/// }
57/// "#;
58/// let out = run(tpl, code, "");
59/// assert_eq!(out.unwrap().stdout, "hello");
60/// }
61/// ```
62///
63pub fn run(tpl: &str, code: &str, input: &str) -> Result<Output, String> {
64 /***
65 * 根据参数生成命令
66 *
67 * 1. 根据模板json数据,解析成结构体 RunTpl
68 * 2. 拼接 写入文件 编译运行文件 命令
69 * 3. 调用exec函数执行 以上命令
70 */
71
72 let run_tpl: RunTpl = match serde_json::from_str(&tpl) {
73 Ok(v) => v,
74 Err(e) => {
75 return Err(format!("运行模板不正确:{}", e));
76 }
77 };
78
79 // 开始结束字符串,随机生成防止内容中包含该字符串导致输入结束
80 let eof = format!("{}", uuid::Uuid::new_v4());
81
82 let cmd = format!(
83 "{}\ncat>{}<<\\{}\n{}\n{}\n{}",
84 if let Some(v) = run_tpl.prev_cmd {
85 v
86 } else {
87 "".to_owned()
88 },
89 run_tpl.file,
90 eof,
91 code,
92 eof,
93 run_tpl.cmd
94 );
95
96 exec(
97 &run_tpl.image,
98 &cmd,
99 input,
100 run_tpl.timeout,
101 &run_tpl.memory,
102 &run_tpl.cpuset,
103 )
104}