pipeline_script/core/
builtin.rs1use std::collections::HashMap;
2use std::ffi::{c_char, c_void, CStr, CString};
3use std::io;
4use std::process::{Command, Stdio};
5use std::sync::Mutex;
6use std::thread::{self, JoinHandle};
7use std::time::{Duration, SystemTime, UNIX_EPOCH};
8
9use lazy_static::lazy_static;
10
11#[repr(C)]
12#[derive(Clone, Copy)]
13pub struct Array {
14 len: i64,
15 ptr: *mut Any,
16}
17#[repr(C)]
18#[derive(Clone, Copy)]
19pub struct Any {
20 id: i32,
21 ptr: *mut i8,
22}
23#[allow(unused)]
24pub extern "C" fn len(target: Array) -> i64 {
25 target.len
26}
27
28pub extern "C" fn hashmap() -> *mut c_void {
37 let map = Box::new(HashMap::<String, String>::new());
38 Box::into_raw(map) as *mut c_void
39}
40
41pub(crate) extern "C" fn hashmap_insert(
51 map_ptr: *mut c_void,
52 key: *const c_char,
53 value: *const c_char,
54) {
55 if map_ptr.is_null() || key.is_null() || value.is_null() {
56 return;
57 }
58
59 let map = unsafe { &mut *(map_ptr as *mut HashMap<String, String>) };
60 let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap_or("").to_string() };
61 let value_str = unsafe { CStr::from_ptr(value).to_str().unwrap_or("").to_string() };
62
63 map.insert(key_str, value_str);
64}
65
66pub(crate) extern "C" fn hashmap_get(map_ptr: *mut c_void, key: *const c_char) -> *mut c_char {
78 if map_ptr.is_null() || key.is_null() {
79 return std::ptr::null_mut();
80 }
81
82 let map = unsafe { &*(map_ptr as *const HashMap<String, String>) };
83 let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap_or("") };
84
85 match map.get(key_str) {
86 Some(value) => match CString::new(value.clone()) {
87 Ok(c_string) => c_string.into_raw(),
88 Err(_) => std::ptr::null_mut(),
89 },
90 None => std::ptr::null_mut(),
91 }
92}
93
94pub(crate) extern "C" fn hashmap_remove(map_ptr: *mut c_void, key: *const c_char) -> bool {
103 if map_ptr.is_null() || key.is_null() {
104 return false;
105 }
106
107 let map = unsafe { &mut *(map_ptr as *mut HashMap<String, String>) };
108 let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap_or("") };
109
110 map.remove(key_str).is_some()
111}
112
113pub(crate) extern "C" fn hashmap_contains_key(map_ptr: *mut c_void, key: *const c_char) -> bool {
122 if map_ptr.is_null() || key.is_null() {
123 return false;
124 }
125
126 let map = unsafe { &*(map_ptr as *const HashMap<String, String>) };
127 let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap_or("") };
128
129 map.contains_key(key_str)
130}
131
132pub extern "C" fn hashmap_len(map_ptr: *mut c_void) -> i64 {
140 if map_ptr.is_null() {
141 return 0;
142 }
143
144 let map = unsafe { &*(map_ptr as *const HashMap<String, String>) };
145 map.len() as i64
146}
147
148pub extern "C" fn hashmap_clear(map_ptr: *mut c_void) {
153 if map_ptr.is_null() {
154 return;
155 }
156
157 let map = unsafe { &mut *(map_ptr as *mut HashMap<String, String>) };
158 map.clear();
159}
160
161pub extern "C" fn hashmap_free(map_ptr: *mut c_void) {
169 if map_ptr.is_null() {
170 return;
171 }
172
173 unsafe {
174 let _map = Box::from_raw(map_ptr as *mut HashMap<String, String>);
175 }
177}
178pub(crate) extern "C" fn println(l: i64, ptr: *mut Any) {
179 for i in 0..l {
180 let obj = unsafe { (ptr).offset(i as isize) };
181 unsafe {
182 match (*obj).id {
183 0 => {
184 print!("Unit")
185 }
186 1 => {
187 let b = (*obj).ptr as *mut bool;
188 print!("{}", *b);
189 }
190 3 => {
191 let value = (*obj).ptr as i8;
192 print!("{}", value);
193 }
194 5 => {
195 let value = (*obj).ptr as i16;
196 print!("{}", value);
197 }
198 7 => {
199 let v = (*obj).ptr as i32;
200 print!("{}", v);
201 }
202 9 => {
203 let v = (*obj).ptr as i64;
204 print!("{}", v);
205 }
206 11 => {
207 let v = (*obj).ptr as *mut f32;
208 print!("{}", *v);
209 }
210 13 => {
211 let v = (*obj).ptr as *mut f64;
212 print!("{}", *v);
213 }
214 15 => {
215 let s = CStr::from_ptr((*obj).ptr as *const c_char);
216 match s.to_str() {
217 Ok(s) => print!("{}", s),
218 Err(_) => print!("InvalidUTF8String"),
219 }
220 }
221 17 => {
222 print!("Any")
223 }
224 _ => {
225 print!("Unknown(id:{}, ptr:{:p})", (*obj).id, (*obj).ptr);
227 }
228 }
229 if i < l - 1 {
230 print!("\t")
231 }
232 }
233 }
234 println!()
235}
236#[allow(unused)]
237pub extern "C" fn print(obj: Array) {
238 for i in 0..obj.len {
239 let obj = unsafe { (obj.ptr).offset(i as isize) };
240 unsafe {
241 match (*obj).id {
242 0 => {
243 print!("Unit")
244 }
245 1 => {
246 let b = (*obj).ptr as *mut bool;
247 print!("{}", *b);
248 }
249 3 => {
250 let value = (*obj).ptr as i8;
251 print!("{}", value);
252 }
253 5 => {
254 let value = (*obj).ptr as i16;
255 print!("{}", value);
256 }
257 7 => {
258 let v = (*obj).ptr as i32;
259 print!("{}", v);
260 }
261 9 => {
262 let v = (*obj).ptr as i64;
263 print!("{}", v);
264 }
265 11 => {
266 let v = (*obj).ptr as *mut f32;
267 print!("{}", *v);
268 }
269 13 => {
270 let v = (*obj).ptr as *mut f64;
271 print!("{}", *v);
272 }
273 15 => {
274 let s = CStr::from_ptr((*obj).ptr as *const c_char);
275 match s.to_str() {
276 Ok(s) => print!("{}", s),
277 Err(_) => print!("InvalidUTF8String"),
278 }
279 }
280 17 => {
281 print!("Any")
282 }
283 _ => {
284 print!("Unknown(id:{})", (*obj).id);
285 }
286 }
287 }
288 }
289}
290pub(crate) extern "C" fn append(l: i64, ptr: *mut Any) -> *mut c_char {
291 let mut s = String::new();
292 for i in 0..l {
293 let obj = unsafe { (ptr).offset(i as isize) };
294 unsafe {
295 match (*obj).id {
296 0 => {
297 s.push_str("Unit");
298 }
299 1 => {
300 let b = (*obj).ptr as i8;
301 s.push_str(&format!("{}", b == 1));
302 }
303 3 => {
304 let value = (*obj).ptr as i8;
305 s.push_str(&format!("{}", value));
306 }
307 5 => {
308 let value = (*obj).ptr as i16;
309 s.push_str(&format!("{}", value));
310 }
311 7 => {
312 let value = (*obj).ptr as i32;
313 s.push_str(&format!("{}", value));
314 }
315 9 => {
316 let v = (*obj).ptr as i64;
317 s.push_str(&format!("{}", v));
318 }
319 11 => {
320 let v = (*obj).ptr as *const f32;
321 s.push_str(&format!("{}", *v));
322 }
323 13 => {
324 let v = (*obj).ptr as *mut f64;
325 s.push_str(&format!("{}", *v));
326 }
327 15 => {
328 let s0 = CStr::from_ptr((*obj).ptr as *const c_char);
329 match s0.to_str() {
330 Ok(str_val) => s.push_str(str_val),
331 Err(_) => s.push_str("InvalidUTF8String"),
332 }
333 }
334 17 => {
335 s.push_str("Any");
336 }
337 _ => {
338 s.push_str(&format!("Unknown(id:{})", (*obj).id));
339 }
340 }
341 }
342 }
343 s.push('\0');
344 let s = s.leak();
345 s.as_ptr() as *mut c_char
346}
347lazy_static! {
348 static ref WORKSPACES: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new());
352
353 static ref THREAD_HANDLES: Mutex<Vec<JoinHandle<()>>> = Mutex::new(Vec::new());
356}
357pub(crate) extern "C" fn cmd(key: *mut c_char, command: *mut c_char) {
369 let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap() };
370 let cmd = unsafe { CStr::from_ptr(command).to_str().unwrap() };
371
372 let workspaces = WORKSPACES.lock().unwrap();
373 let binding = "./".to_string();
374 let workspace = workspaces.get(key_str).unwrap_or(&binding);
375 #[allow(clippy::zombie_processes)]
376 Command::new("powershell")
377 .current_dir(workspace)
378 .arg("/C")
379 .arg(cmd)
380 .stdout(Stdio::inherit())
381 .stderr(Stdio::inherit())
382 .spawn()
383 .expect("Failed to execute command");
384}
385pub(crate) extern "C" fn workspace(key: *mut c_char, dir: *mut c_char) {
396 let key_str = unsafe { CStr::from_ptr(key).to_str().unwrap() };
397 let dir_str = unsafe { CStr::from_ptr(dir).to_str().unwrap() };
398
399 if !std::path::Path::new(dir_str).exists() {
401 panic!("Directory does not exist: {}", dir_str);
402 }
403
404 let mut workspaces = WORKSPACES.lock().unwrap();
406 workspaces.insert(key_str.to_string(), dir_str.to_string());
407}
408#[allow(unused)]
409pub extern "C" fn exit() {
410 std::process::exit(0);
411}
412#[allow(unused)]
413pub(crate) extern "C" fn get_env(key: *mut c_char) -> *mut c_char {
414 let key = unsafe { CStr::from_ptr(key).to_str().unwrap() };
415 let mut value = std::env::var(key).unwrap();
416 value.push('\0');
417 let value = value.leak();
418 value.as_ptr() as *mut c_char
419}
420#[allow(unused)]
421pub(crate) extern "C" fn set_env(key: *mut c_char, value: *mut c_char) {
422 let key = unsafe { CStr::from_ptr(key).to_str().unwrap() };
423 let value = unsafe { CStr::from_ptr(value).to_str().unwrap() };
424 std::env::set_var(key, value);
425}
426
427#[allow(unused)]
428pub(crate) extern "C" fn panic(ptr: *mut c_char) {
429 let s = unsafe { CStr::from_ptr(ptr).to_str().unwrap() };
430 eprintln!("\x1b[31mpanic: {}\x1b[0m", s);
431 std::process::exit(1);
432}
433
434#[no_mangle]
435pub extern "C" fn now() -> u64 {
436 SystemTime::now()
437 .duration_since(UNIX_EPOCH)
438 .unwrap_or_default() .as_millis() as u64 }
441
442pub type ExternFn = extern "C" fn(*const u8);
444
445pub extern "C" fn spawn0(func: ExternFn, _env: *const c_char, name: *const c_char) {
454 let name = unsafe { CStr::from_ptr(name).to_str().unwrap() };
455 let handle = thread::spawn(move || {
457 func(name.as_ptr());
458 });
459
460 let mut handles = THREAD_HANDLES.lock().unwrap();
462 handles.push(handle);
463}
464
465pub extern "C" fn wait() {
471 let mut handles = THREAD_HANDLES.lock().unwrap();
472
473 while let Some(handle) = handles.pop() {
475 if let Err(e) = handle.join() {
476 eprintln!("线程执行失败: {:?}", e);
477 }
478 }
479}
480
481pub extern "C" fn sleep(ms: u64) {
482 thread::sleep(Duration::from_millis(ms));
483}
484
485pub(crate) extern "C" fn string_equal(l: *const c_char, r: *const c_char) -> bool {
486 let l = unsafe { CStr::from_ptr(l).to_str().unwrap() };
487 let r = unsafe { CStr::from_ptr(r).to_str().unwrap() };
488 l.eq(r)
489}
490
491pub extern "C" fn read_line() -> *mut c_char {
500 let mut input = String::new();
501 match io::stdin().read_line(&mut input) {
502 Ok(_) => {
503 match CString::new(input) {
505 Ok(c_string) => c_string.into_raw(),
506 Err(_) => {
507 CString::new("").unwrap().into_raw()
509 }
510 }
511 }
512 Err(_) => {
513 CString::new("").unwrap().into_raw()
515 }
516 }
517}
518
519pub extern "C" fn read_string() -> *mut c_char {
528 let mut input = String::new();
529 match io::stdin().read_line(&mut input) {
530 Ok(_) => {
531 let trimmed = input.trim_end().to_string();
533 match CString::new(trimmed) {
534 Ok(c_string) => c_string.into_raw(),
535 Err(_) => {
536 CString::new("").unwrap().into_raw()
538 }
539 }
540 }
541 Err(_) => {
542 CString::new("").unwrap().into_raw()
544 }
545 }
546}
547
548pub extern "C" fn read_int64() -> i64 {
557 let mut input = String::new();
558 match io::stdin().read_line(&mut input) {
559 Ok(_) => {
560 match input.trim().parse::<i64>() {
562 Ok(num) => num,
563 Err(_) => {
564 eprintln!("警告: 输入的不是有效的整数,返回默认值 0");
565 0
566 }
567 }
568 }
569 Err(_) => {
570 eprintln!("错误: 读取输入失败,返回默认值 0");
571 0
572 }
573 }
574}
575
576pub extern "C" fn read_double() -> f64 {
585 let mut input = String::new();
586 match io::stdin().read_line(&mut input) {
587 Ok(_) => {
588 match input.trim().parse::<f64>() {
590 Ok(num) => num,
591 Err(_) => {
592 eprintln!("警告: 输入的不是有效的浮点数,返回默认值 0.0");
593 0.0
594 }
595 }
596 }
597 Err(_) => {
598 eprintln!("错误: 读取输入失败,返回默认值 0.0");
599 0.0
600 }
601 }
602}
603pub extern "C" fn read_float() -> f32 {
612 let mut input = String::new();
613 match io::stdin().read_line(&mut input) {
614 Ok(_) => {
615 match input.trim().parse::<f32>() {
617 Ok(num) => num,
618 Err(_) => {
619 eprintln!("警告: 输入的不是有效的浮点数,返回默认值 0.0");
620 0.0
621 }
622 }
623 }
624 Err(_) => {
625 eprintln!("错误: 读取输入失败,返回默认值 0.0");
626 0.0
627 }
628 }
629}