pub mod cli_utils {
use crate::core::RUMResult;
use crate::strings::{rumtk_format, RUMArrayConversions, RUMString};
use clap::Parser;
use compact_str::CompactStringExt;
use std::io::{stdin, stdout, Read, StdinLock, Write};
use std::num::NonZeroU16;
const BUFFER_SIZE: usize = 1024 * 4;
const BUFFER_CHUNK_SIZE: usize = 512;
pub type BufferSlice = Vec<u8>;
pub type BufferChunk = [u8; BUFFER_CHUNK_SIZE];
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct RUMTKArgs {
#[arg(short, long)]
ip: Option<RUMString>,
#[arg(short, long)]
port: Option<NonZeroU16>,
#[arg(short, long)]
x: Option<RUMString>,
#[arg(short, long, default_value_t = 1)]
threads: usize,
#[arg(short, long)]
outbound: bool,
#[arg(short, long, default_value_t = false)]
debug: bool,
#[arg(short, long, default_value_t = false)]
dry_run: bool,
}
pub fn read_stdin() -> RUMResult<RUMString> {
let mut stdin_lock = stdin().lock();
let mut stdin_buffer: Vec<u8> = Vec::with_capacity(BUFFER_SIZE);
let mut s = read_some_stdin(&mut stdin_lock, &mut stdin_buffer)?;
while s == BUFFER_CHUNK_SIZE {
s = read_some_stdin(&mut stdin_lock, &mut stdin_buffer)?;
}
let mut filtered = Vec::<u8>::with_capacity(stdin_buffer.len());
for c in stdin_buffer {
if c != 0 {
filtered.push(c);
}
}
Ok(filtered.to_rumstring())
}
pub fn read_some_stdin(input: &mut StdinLock, buf: &mut BufferSlice) -> RUMResult<usize> {
let mut chunk: BufferChunk = [0; BUFFER_CHUNK_SIZE];
match input.read(&mut chunk) {
Ok(s) => {
buf.extend_from_slice(&chunk);
Ok(s)
}
Err(e) => Err(rumtk_format!("Error reading stdin chunk because {}!", e)),
}
}
pub fn write_stdout(data: &RUMString) -> RUMResult<()> {
let mut stdout_handle = stdout();
match stdout_handle.write_all(data.as_bytes()) {
Ok(_) => match stdout_handle.flush() {
Ok(_) => Ok(()),
Err(e) => Err(rumtk_format!("Error flushing stdout: {}", e)),
},
Err(e) => Err(rumtk_format!("Error writing to stdout!")),
}
}
pub fn print_license_notice(program: &str, year: &str, author_list: &Vec<&str>) {
let authors = author_list.join_compact(", ");
let notice = rumtk_format!(
" {program} Copyright (C) {year} {authors}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details."
);
println!("{}", notice);
}
}
pub mod macros {
#[macro_export]
macro_rules! rumtk_read_stdin {
( ) => {{
use $crate::cli::cli_utils::read_stdin;
read_stdin()
}};
}
#[macro_export]
macro_rules! rumtk_write_stdout {
( $message:expr ) => {{
use $crate::cli::cli_utils::write_stdout;
use $crate::strings::basic_escape;
let escaped_message = basic_escape($message);
write_stdout(&escaped_message);
}};
}
#[macro_export]
macro_rules! rumtk_print_license_notice {
( ) => {{
use $crate::cli::cli_utils::print_license_notice;
print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
}};
( $program:expr ) => {{
use $crate::cli::cli_utils::print_license_notice;
print_license_notice(&$program, "2025", &vec!["2025", "Luis M. Santos, M.D."]);
}};
( $program:expr, $year:expr ) => {{
use $crate::cli::cli_utils::print_license_notice;
print_license_notice(&$program, &$year, &vec!["Luis M. Santos, M.D."]);
}};
( $program:expr, $year:expr, $authors:expr ) => {{
use $crate::cli::cli_utils::print_license_notice;
print_license_notice(&$program, &$year, &$authors);
}};
}
}