//#[inline]
fn reverse < T > ( 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 < V > + ' 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 ,
}
}
trait Input : AsRef < [ u8 ] > + std ::fmt ::Debug { }
impl < T : ? Sized > Input for T
where T : AsRef < [ u8 ] > + std ::fmt ::Debug { }
fn collect_input ( ) -> Box < dyn Iterator < Item = impl Input + ' static > + ' static >
{
use std ::{
ffi ::{ OsStr , OsString } ,
os ::unix ::ffi ::* ,
} ;
//#[derive(Debug)]
enum MaybeUTF8
{
UTF8 ( String ) ,
Raw ( OsString ) ,
Static ( & ' static [ u8 ] ) ,
}
impl std ::fmt ::Debug for MaybeUTF8
{
// Custom Debug impl to ensure output is identical when `output-quoted` is enabled.
#[ inline ]
fn fmt ( & self , f : & mut std ::fmt ::Formatter < ' _ > ) -> std ::fmt ::Result
{
let dbg : & dyn std ::fmt ::Debug = match self {
Self ::UTF8 ( string ) = > string ,
Self ::Raw ( raw ) = > raw ,
Self ::Static ( & [ ] ) = > return f . write_str ( "\"\"" ) ,
Self ::Static ( bytes ) = > return std ::fmt ::Debug ::fmt ( OsStr ::from_bytes ( bytes ) , f ) ,
} ;
std ::fmt ::Debug ::fmt ( dbg , f )
}
}
impl AsRef < [ u8 ] > for MaybeUTF8
{
#[ inline ]
fn as_ref ( & self ) -> & [ u8 ]
{
match self {
Self ::UTF8 ( string ) = > string . as_bytes ( ) ,
Self ::Raw ( raw ) = > raw . as_bytes ( ) ,
Self ::Static ( bytes ) = > bytes ,
}
}
}
impl From < String > for MaybeUTF8
{
#[ inline(always) ]
fn from ( from : String ) -> Self
{
Self ::UTF8 ( from )
}
}
impl From < OsString > for MaybeUTF8
{
#[ inline(always) ]
fn from ( from : OsString ) -> Self
{
Self ::Raw ( from )
}
}
impl MaybeUTF8
{
#[ inline(always) ]
pub const fn from_static_bytes ( bytes : & ' static [ u8 ] ) -> Self
{
Self ::Static ( bytes )
}
#[ inline(always) ]
pub fn from_raw_bytes ( bytes : & [ u8 ] ) -> Self
{
Self ::Raw ( OsStr ::from_bytes ( bytes ) . to_os_string ( ) )
}
#[ inline(always) ]
//#[deprecated(note="XXX: TODO: Only use this if the read_until() into vec does not add the '\n' into the vec as well. Otherwise, *always* use this.")]
pub fn from_raw_vec ( vec : Vec < u8 > ) -> Self
{
Self ::Raw ( OsString ::from_vec ( vec ) )
}
}
if std ::env ::args_os ( ) . len ( ) < = 1 {
use std ::io ::{
self ,
BufRead ,
} ;
// No args, collect stdin lines
if ! cfg! ( feature = "byte-strings" ) {
// Collect utf8 string lines
Box ::new ( io ::stdin ( )
. lock ( )
. lines ( )
. filter_map ( Result ::ok )
. map ( MaybeUTF8 ::from ) )
} else {
// Collect arbitrary byte strings
struct OsLineReader < ' a > ( io ::StdinLock < ' a > , Vec < u8 > ) ;
impl < ' a > Iterator for OsLineReader < ' a >
{
type Item = MaybeUTF8 ;
fn next ( & mut self ) -> Option < Self ::Item >
{
Some ( match handle_fmt_err_or ( self . 0. read_until ( b'\n' , & mut self . 1 ) , | | 0 ) {
0 = > return None ,
1 if self . 1 [ 0 ] = = b'\n' = > MaybeUTF8 ::from_static_bytes ( & [ ] ) ,
read_sz = > {
let line = if self . 1 [ read_sz - 1 ] = = b'\n' {
MaybeUTF8 ::from_raw_bytes ( & self . 1 [ .. ( read_sz - 1 ) ] )
} else {
MaybeUTF8 ::from_raw_vec ( self . 1. clone ( ) )
} ;
debug_assert_ne! ( line . as_ref ( ) . iter ( ) . last ( ) . copied ( ) , Some ( b'\n' ) , "Deliminator still in output" ) ;
self . 1. clear ( ) ;
line
} ,
} )
}
}
Box ::new ( OsLineReader ( io ::stdin ( ) . lock ( ) , // Acquire the lock until the iterator is consumed (like all other paths in this function)
Vec ::with_capacity ( 4096 ) ) ) // Buffer of size 4k
}
} else {
// Has arguments, return them
if cfg! ( feature = "byte-strings" ) {
Box ::new ( std ::env ::args_os ( ) . skip ( 1 ) . map ( MaybeUTF8 ::from ) )
} else if cfg! ( feature = "ignore-invalid-args" ) {
Box ::new ( std ::env ::args_os ( ) . skip ( 1 ) . filter_map ( | os | os . into_string ( ) . ok ( ) ) . map ( MaybeUTF8 ::from ) )
} else {
Box ::new ( std ::env ::args_os ( ) . skip ( 1 ) . map ( | os | os . to_string_lossy ( ) . into_owned ( ) . into ( ) ) )
}
}
}
#[ allow(dead_code) ]
#[ cfg_attr(feature= " ignore-output-errors " , inline) ]
fn handle_fmt_err_or < F , T > ( res : std ::io ::Result < T > , or : F ) -> T
where F : FnOnce ( ) -> T
{
#[ cfg(not(feature= " ignore-output-errors " )) ] {
match res {
Ok ( v ) = > return v ,
Err ( e ) = > eprintln! ( "[!] failed to write line: {e}" ) ,
}
return or ( ) ;
}
#[ cfg(feature= " ignore-output-errors " ) ]
res . unwrap_or_else ( | _ | or ( ) )
}
#[ allow(dead_code) ]
#[ cfg_attr(feature= " ignore-output-errors " , inline(always)) ]
fn handle_fmt_err < T > ( res : std ::io ::Result < T > )
{
#[ 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_ref ( ) )
. 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 ) ;
}