mod args; mod charset; mod color; use libc::{c_char, c_int, c_void}; use std::ffi::CString; use std::process; use color::Color; const VERSION: &str = "2.0.0"; extern "C" { fn nmstermio_set_clearscr(_: c_int); fn nmseffect_exec( input: *const c_char, len: c_int, autodecrypt_c: c_int, maskblank_c: c_int, clear_scr: c_int, ) -> c_char; static mut foregroundColor: c_int; } ///Sleep for the number of milliseconds indicated by argument #[no_mangle] pub extern "C" fn nmseffect_sleep(t: c_int) { use std::time::Duration; let dur = Duration::from_millis(t as u64); std::thread::sleep(dur); } /// Return a random character from charTable[]. #[no_mangle] pub extern "C" fn nmscharset_get_random() -> *const c_char { let table = charset::CHAR_TABLE; let idx: u16 = rand::random::(); let bytes = table[(idx as usize) % table.len()]; bytes.as_ptr() as *const c_char } #[no_mangle] pub extern "C" fn rust_main() { println!("Hello from rust"); let args = match args::parse_arguments() { Ok(args) => args, Err(e) => { println!("{e}"); process::exit(1); } }; println!("{:?}", args); if args.version { println!("nms version {VERSION}"); process::exit(0); } if let Some(color) = args.foreground { let color = Color::try_from(color).unwrap_or_default(); let n = color as c_int; unsafe { foregroundColor = n; } } if args.clear_screen { unsafe { nmstermio_set_clearscr(2); } } let input = get_input("Enter input: "); if input.len() == 0 { eprintln!("Input is empty"); //TODO use error_log()/error_print() abstraction process::exit(1); } exec_effect(input, args.autodecrypt, args.mask_blanks, args.clear_screen); } fn exec_effect(input: String, autodecrypt: bool, maskblank: bool, clear_screen: bool) { let maskblank_c = if maskblank { 1 } else { 0 }; let autodecrypt_c = if autodecrypt { 1 } else { 0}; let output_cstring = CString::new(input).unwrap(); let ptr = output_cstring.as_ptr(); let len = output_cstring.as_bytes().len(); let clear = if clear_screen { 1 } else { 0 }; let _r = unsafe { nmseffect_exec(ptr, len as i32, autodecrypt_c, maskblank_c, clear) }; } fn get_input(prompt: &str) -> String { use std::io::{Read, Write}; let mut stdin = std::io::stdin(); let mut stdout = std::io::stdout(); let mut buf = String::new(); if atty::is(atty::Stream::Stdin) { print!("{prompt}"); stdout.flush().unwrap(); stdin.read_line(&mut buf).unwrap(); } else { stdin.read_to_string(&mut buf).unwrap(); } buf }