use std::{ env::args, io::{ stdin, stdout, Error, ErrorKind, Read, Write }, process::ExitCode, vec::Vec }; extern crate getopt; use getopt::{ Opt, Parser }; extern crate sysexits; use sysexits::{ EX_OK, EX_OSERR, EX_USAGE }; fn oserr(s: &str, e: Error) -> ExitCode { eprintln!("{}: {}", s, e); ExitCode::from(EX_OSERR as u8) } fn usage(s: &str) -> ExitCode { eprintln!("Usage: {} (-f) (-w [wordsize])", s); ExitCode::from(EX_USAGE as u8) } fn main() -> ExitCode { let argv = args().collect::>(); let mut buf: Vec = Vec::new(); let mut input = stdin(); let mut output = stdout().lock(); let mut opts = Parser::new(&argv, "fw:"); let mut force = false; let mut wordsize: usize = 2; loop { match opts.next() { None => break, Some(opt) => match opt { Ok(Opt('f', None)) => force = true, Ok(Opt('w', Some(arg))) => { match arg.parse::() { Ok(w) if w % 2 == 0 => { wordsize = w; () }, _ => { return usage(&argv[0]); }, } }, _ => { return usage(&argv[0]); } } } } buf.resize(wordsize, 0); loop { match input.read(&mut buf) { Ok(0) => break ExitCode::from(EX_OK as u8), Ok(v) if v == wordsize => { let (left, right) = buf.split_at(v/2); if let Err(e) = output.write(&right) .and_then(|_| output.write(&left)) { break oserr(&argv[0], e) } }, Ok(v) => { if let Err(e) = output.write(&buf[..v]) { break oserr(&argv[0], e) } }, Err(e) if e.kind() == ErrorKind::Interrupted && force => continue, Err(e) => break oserr(&argv[0], e) } } }