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 nmseffect_set_clearscr(_: c_int) -> c_void; fn nmseffect_exec(input: *const c_char, len: c_int, autodecrypt_c: c_int) -> c_char; static mut foregroundColor: c_int; static mut maskBlank: c_int; } /// 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; } } unsafe { if args.mask_blanks { maskBlank = 1; } else { maskBlank = 0; } } if args.clear_screen { unsafe { nmseffect_set_clearscr(1); } } let autodecrypt_c = if args.autodecrypt { 1 } else { 0 }; let output = get_input("Enter input: "); if output.len() == 0 { eprintln!("Input is empty"); //TODO use error_log()/error_print() abstraction process::exit(1); } let output_cstring = CString::new(output).unwrap(); let ptr = output_cstring.as_ptr(); let len = output_cstring.as_bytes().len(); let _r = unsafe { nmseffect_exec(ptr, len as i32, autodecrypt_c) }; } 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 }