pipeline_script/core/
builtin.rs1use std::ffi::{c_char, CStr};
2use std::process::{Command, Stdio};
3use std::sync::Mutex;
4use std::thread::{self};
5use std::time::{Duration, SystemTime, UNIX_EPOCH};
6
7use lazy_static::lazy_static;
8
9#[repr(C)]
10pub struct Array {
11 len: i64,
12 ptr: *mut Any,
13}
14#[repr(C)]
15pub struct Any {
16 id: i32,
17 ptr: *mut i8,
18}
19#[allow(unused)]
20pub extern "C" fn len(target: Array) -> i64 {
21 target.len
22}
23pub extern "C" fn println(obj: Any) {
24 unsafe {
25 match obj.id {
26 0 => {
27 print!("Unit")
28 }
29 1 => {
30 let b = obj.ptr as *mut bool;
31 print!("{}", *b);
32 }
33 3 => {
34 let value = obj.ptr as i8;
35 print!("{}", value);
36 }
37 5 => {
38 let value = obj.ptr as i16;
39 print!("{}", value);
40 }
41 7 => {
42 let v = obj.ptr as i32;
43 print!("{}", v);
44 }
45 9 => {
46 let v = obj.ptr as i64;
47 print!("{}", v);
48 }
49 11 => {
50 let v = obj.ptr as *mut f32;
51 print!("{}", *v);
52 }
53 13 => {
54 let v = obj.ptr as *mut f64;
55 print!("{}", *v);
56 }
57 15 => {
58 let s = CStr::from_ptr(obj.ptr as *const c_char);
59 print!("{}", s.to_str().unwrap());
60 }
61
62 t => todo!("{t}"),
63 }
64 }
65 println!()
67}
68#[allow(unused)]
69pub extern "C" fn print(obj: Array) {
70 for i in 0..obj.len {
71 let obj = unsafe { (obj.ptr).offset(i as isize) };
72 unsafe {
73 match (*obj).id {
74 0 => {
75 print!("Unit")
76 }
77 3 => {
78 let value = (*obj).ptr as i32;
79 print!("{}", value);
80 }
81 4 => {
82 let v = (*obj).ptr as i64;
83 print!("{}", v);
84 }
85 7 => {
86 let s = CStr::from_ptr((*obj).ptr as *const c_char);
87 print!("{}", s.to_str().unwrap());
88 }
89 t => todo!("{t}"),
90 }
91 }
92 }
93}
94pub extern "C" fn append(obj: Array) -> *mut c_char {
95 let mut s = String::new();
96 for i in 0..obj.len {
97 let obj = unsafe { (obj.ptr).offset(i as isize) };
98 unsafe {
99 match (*obj).id {
100 0 => {
101 s.push_str("Unit");
102 }
103 3 => {
104 let value = (*obj).ptr as i32;
105 s.push_str(&format!("{}", value));
106 }
107 4 => {
108 let v = (*obj).ptr as i64;
109 s.push_str(&format!("{}", v));
110 }
111 7 => {
112 let s0 = CStr::from_ptr((*obj).ptr as *const c_char);
113 s.push_str(s0.to_str().unwrap());
114 }
115 t => todo!("{t}"),
116 }
117 }
118 }
119 s.push('\0');
120 let s = s.leak();
121 s.as_ptr() as *mut c_char
122}
123lazy_static! {
124 static ref WORKSPACE: Mutex<String> = Mutex::new("./".to_string());
127}
128pub extern "C" fn cmd(command: *mut c_char) {
137 let cmd = unsafe { CStr::from_ptr(command).to_str().unwrap() };
138 let workspace = WORKSPACE.lock().unwrap();
139 Command::new("powershell")
140 .current_dir(workspace.as_str())
141 .arg("/C")
142 .arg(cmd)
143 .stdout(Stdio::inherit())
144 .stderr(Stdio::inherit())
145 .output()
146 .expect("Failed to execute command");
147}
148pub extern "C" fn workspace(dir: *mut c_char) {
157 let dir_str = unsafe { CStr::from_ptr(dir).to_str().unwrap() };
158
159 if !std::path::Path::new(dir_str).exists() {
161 panic!("Directory does not exist: {}", dir_str);
162 }
163
164 let mut workspace = WORKSPACE.lock().unwrap();
166 *workspace = dir_str.to_string();
167}
168#[allow(unused)]
169pub extern "C" fn exit() {
170 std::process::exit(0);
171}
172#[allow(unused)]
173pub extern "C" fn get_env(key: *mut c_char) -> *mut c_char {
174 let key = unsafe { CStr::from_ptr(key).to_str().unwrap() };
175 let mut value = std::env::var(key).unwrap();
176 value.push('\0');
177 let value = value.leak();
178 value.as_ptr() as *mut c_char
179}
180#[allow(unused)]
181pub extern "C" fn set_env(key: *mut c_char, value: *mut c_char) {
182 let key = unsafe { CStr::from_ptr(key).to_str().unwrap() };
183 let value = unsafe { CStr::from_ptr(value).to_str().unwrap() };
184 std::env::set_var(key, value);
185}
186
187#[allow(unused)]
188pub extern "C" fn panic(ptr: *mut c_char) {
189 let s = unsafe { CStr::from_ptr(ptr).to_str().unwrap() };
190 eprintln!("\x1b[31mpanic: {}\x1b[0m", s);
191 std::process::exit(1);
192}
193
194#[no_mangle]
195pub extern "C" fn now() -> u64 {
196 SystemTime::now()
197 .duration_since(UNIX_EPOCH)
198 .unwrap_or_default() .as_millis() as u64 }
201
202pub type ExternFn = extern "C" fn();
204
205pub extern "C" fn spawn(func: ExternFn) {
206 thread::spawn(move || {
208 func();
209 });
210}
211
212pub extern "C" fn sleep(ms: u64) {
213 thread::sleep(Duration::from_millis(ms));
214}