//#[inline] fn reverse(slice: &mut [T]) { match slice { [ref mut a, ref mut rest @ .., ref mut b] => { std::mem::swap(a, b); reverse(rest) }, [] | [_] => (), } } /// This actually works! And is so easily parallelisable with something like rayon, or asyncing by spawning/creating the tail-call into a new task, then either waiting them concurrently or in parallen (spawn or created future from just calling the function without awaiting it) #[allow(dead_code)] fn binsearch<'a, V: ?Sized, T: PartialEq + 'a>(slice: &'a [T], find: &V) -> Option<&'a T> { match slice { [ref a, pivot @ .., ref b] => { match (a==find, b==find) { (true, _) => Some(a), (_, true) => Some(b), _ => binsearch(pivot, find), } }, [ref a] if a == find => Some(a), _ => None, } } fn collect_input() -> Box + 'static> { // TODO: Use non-panicking functions for both reading lines and reading args, just skip invalid lines/args if std::env::args_os().len() <= 1 { use std::io::{ self, BufRead, }; // No args, collect stdin lines Box::new(io::stdin() .lock() .lines() .filter_map(Result::ok)) } else { // Has arguments, return them if cfg!(feature="ignore-invalid-args") { Box::new(std::env::args_os().skip(1).filter_map(|os| os.into_string().ok())) } else { Box::new(std::env::args_os().skip(1).map(|os| os.to_string_lossy().into_owned())) } } } #[cfg_attr(feature="ignore-output-errors", inline(always))] fn handle_fmt_err(res: std::io::Result) { #[cfg(not(feature="ignore-output-errors"))] if let Err(e) = res { eprintln!("[!] failed to write line: {e}"); } let _ = res; } fn main() { let mut args: Vec = collect_input().collect(); reverse(&mut args[..]); //eprintln!("{:?}", binsearch(&args[..], "1")); // It works! #[cfg(feature="output-lines")] { #[allow(unused_imports)] use std::io::{ Write, BufWriter, }; #[cfg(feature="buffer-output")] let mut out = BufWriter::new(std::io::stdout().lock()); #[cfg(not(feature="buffer-output"))] let mut out = std::io::stdout().lock(); for x in args.iter() { handle_fmt_err({ if cfg!(feature="output-quoted") { //XXX: This doesn't flush, right? It shouldn't, but maybe we should test it? writeln!(&mut out, "{:?}", x) } else { //writeln!(&mut out, "{}", x) out.write(x.as_bytes()) .and_then(|_| out.write(b"\n")) .map(|_| {}) } }); } //#[cfg(feature="buffer-output")] handle_fmt_err(out.flush()); //XXX: Do we need to flush when not buffering output? Does it matter since buffering output will be enabled by default and should almost always be enabled? } #[cfg(not(feature="output-lines"))] println!("{:?}", args); }