@@ -8,7 +8,8 @@ use crate::fmt;
88use  crate :: fs:: File ; 
99use  crate :: io:: prelude:: * ; 
1010use  crate :: io:: { 
11-     self ,  BorrowedCursor ,  BufReader ,  IoSlice ,  IoSliceMut ,  LineWriter ,  Lines ,  SpecReadByte , 
11+     self ,  BorrowedCursor ,  BufReader ,  BufWriter ,  IoSlice ,  IoSliceMut ,  LineWriter ,  Lines , 
12+     SpecReadByte , 
1213} ; 
1314use  crate :: panic:: { RefUnwindSafe ,  UnwindSafe } ; 
1415use  crate :: sync:: atomic:: { Atomic ,  AtomicBool ,  Ordering } ; 
@@ -43,19 +44,19 @@ static OUTPUT_CAPTURE_USED: Atomic<bool> = AtomicBool::new(false);
4344/// 
4445/// This handle is not synchronized or buffered in any fashion. Constructed via 
4546/// the `std::io::stdio::stdin_raw` function. 
46- struct  StdinRaw ( stdio:: Stdin ) ; 
47+ pub ( crate )   struct  StdinRaw ( stdio:: Stdin ) ; 
4748
4849/// A handle to a raw instance of the standard output stream of this process. 
4950/// 
5051/// This handle is not synchronized or buffered in any fashion. Constructed via 
5152/// the `std::io::stdio::stdout_raw` function. 
52- struct  StdoutRaw ( stdio:: Stdout ) ; 
53+ pub ( crate )   struct  StdoutRaw ( stdio:: Stdout ) ; 
5354
5455/// A handle to a raw instance of the standard output stream of this process. 
5556/// 
5657/// This handle is not synchronized or buffered in any fashion. Constructed via 
5758/// the `std::io::stdio::stderr_raw` function. 
58- struct  StderrRaw ( stdio:: Stderr ) ; 
59+ pub ( crate )   struct  StderrRaw ( stdio:: Stderr ) ; 
5960
6061/// Constructs a new raw handle to the standard input of this process. 
6162/// 
@@ -576,6 +577,76 @@ impl fmt::Debug for StdinLock<'_> {
576577    } 
577578} 
578579
580+ /// A buffered writer for stdout and stderr. 
581+ /// 
582+ /// This writer may be either [line-buffered](LineWriter) or [block-buffered](BufWriter), depending 
583+ /// on whether the underlying file is a terminal or not. 
584+ #[ derive( Debug ) ]  
585+ enum  StdioBufWriter < W :  Write >  { 
586+     LineBuffered ( LineWriter < W > ) , 
587+     BlockBuffered ( BufWriter < W > ) , 
588+ } 
589+ 
590+ impl < W :  Write  + IsTerminal >  StdioBufWriter < W >  { 
591+     /// Wraps a writer using the most appropriate buffering method. 
592+ /// 
593+ /// If `w` is a terminal, then the resulting `StdioBufWriter` will be line-buffered, otherwise 
594+ /// it will be block-buffered. 
595+ fn  new ( w :  W )  -> Self  { 
596+         if  w. is_terminal ( )  { 
597+             Self :: LineBuffered ( LineWriter :: new ( w) ) 
598+         }  else  { 
599+             Self :: BlockBuffered ( BufWriter :: new ( w) ) 
600+         } 
601+     } 
602+ } 
603+ 
604+ impl < W :  Write >  StdioBufWriter < W >  { 
605+     /// Wraps a writer using a block-buffer with the given capacity. 
606+ fn  with_capacity ( cap :  usize ,  w :  W )  -> Self  { 
607+         Self :: BlockBuffered ( BufWriter :: with_capacity ( cap,  w) ) 
608+     } 
609+ } 
610+ 
611+ impl < W :  Write >  Write  for  StdioBufWriter < W >  { 
612+     fn  write ( & mut  self ,  buf :  & [ u8 ] )  -> io:: Result < usize >  { 
613+         match  self  { 
614+             Self :: LineBuffered ( w)  => w. write ( buf) , 
615+             Self :: BlockBuffered ( w)  => w. write ( buf) , 
616+         } 
617+     } 
618+     fn  write_vectored ( & mut  self ,  bufs :  & [ IoSlice < ' _ > ] )  -> io:: Result < usize >  { 
619+         match  self  { 
620+             Self :: LineBuffered ( w)  => w. write_vectored ( bufs) , 
621+             Self :: BlockBuffered ( w)  => w. write_vectored ( bufs) , 
622+         } 
623+     } 
624+     fn  is_write_vectored ( & self )  -> bool  { 
625+         match  self  { 
626+             Self :: LineBuffered ( w)  => w. is_write_vectored ( ) , 
627+             Self :: BlockBuffered ( w)  => w. is_write_vectored ( ) , 
628+         } 
629+     } 
630+     fn  flush ( & mut  self )  -> io:: Result < ( ) >  { 
631+         match  self  { 
632+             Self :: LineBuffered ( w)  => w. flush ( ) , 
633+             Self :: BlockBuffered ( w)  => w. flush ( ) , 
634+         } 
635+     } 
636+     fn  write_all ( & mut  self ,  buf :  & [ u8 ] )  -> io:: Result < ( ) >  { 
637+         match  self  { 
638+             Self :: LineBuffered ( w)  => w. write_all ( buf) , 
639+             Self :: BlockBuffered ( w)  => w. write_all ( buf) , 
640+         } 
641+     } 
642+     fn  write_all_vectored ( & mut  self ,  bufs :  & mut  [ IoSlice < ' _ > ] )  -> io:: Result < ( ) >  { 
643+         match  self  { 
644+             Self :: LineBuffered ( w)  => w. write_all_vectored ( bufs) , 
645+             Self :: BlockBuffered ( w)  => w. write_all_vectored ( bufs) , 
646+         } 
647+     } 
648+ } 
649+ 
579650/// A handle to the global standard output stream of the current process. 
580651/// 
581652/// Each handle shares a global buffer of data to be written to the standard 
@@ -606,10 +677,9 @@ impl fmt::Debug for StdinLock<'_> {
606677/// [`io::stdout`]: stdout 
607678#[ stable( feature = "rust1" ,  since = "1.0.0" ) ]  
608679pub  struct  Stdout  { 
609-     // FIXME: this should be LineWriter or BufWriter depending on the state of 
610-     //        stdout (tty or not). Note that if this is not line buffered it 
611-     //        should also flush-on-panic or some form of flush-on-abort. 
612-     inner :  & ' static  ReentrantLock < RefCell < LineWriter < StdoutRaw > > > , 
680+     // FIXME: if this is not line buffered it should flush-on-panic or some 
681+     //        form of flush-on-abort. 
682+     inner :  & ' static  ReentrantLock < RefCell < StdioBufWriter < StdoutRaw > > > , 
613683} 
614684
615685/// A locked reference to the [`Stdout`] handle. 
@@ -638,10 +708,10 @@ pub struct Stdout {
638708#[ must_use = "if unused stdout will immediately unlock" ]  
639709#[ stable( feature = "rust1" ,  since = "1.0.0" ) ]  
640710pub  struct  StdoutLock < ' a >  { 
641-     inner :  ReentrantLockGuard < ' a ,  RefCell < LineWriter < StdoutRaw > > > , 
711+     inner :  ReentrantLockGuard < ' a ,  RefCell < StdioBufWriter < StdoutRaw > > > , 
642712} 
643713
644- static  STDOUT :  OnceLock < ReentrantLock < RefCell < LineWriter < StdoutRaw > > > >  = OnceLock :: new ( ) ; 
714+ static  STDOUT :  OnceLock < ReentrantLock < RefCell < StdioBufWriter < StdoutRaw > > > >  = OnceLock :: new ( ) ; 
645715
646716/// Constructs a new handle to the standard output of the current process. 
647717/// 
@@ -716,7 +786,7 @@ static STDOUT: OnceLock<ReentrantLock<RefCell<LineWriter<StdoutRaw>>>> = OnceLoc
716786pub  fn  stdout ( )  -> Stdout  { 
717787    Stdout  { 
718788        inner :  STDOUT 
719-             . get_or_init ( || ReentrantLock :: new ( RefCell :: new ( LineWriter :: new ( stdout_raw ( ) ) ) ) ) , 
789+             . get_or_init ( || ReentrantLock :: new ( RefCell :: new ( StdioBufWriter :: new ( stdout_raw ( ) ) ) ) ) , 
720790    } 
721791} 
722792
@@ -727,7 +797,7 @@ pub fn cleanup() {
727797    let  mut  initialized = false ; 
728798    let  stdout = STDOUT . get_or_init ( || { 
729799        initialized = true ; 
730-         ReentrantLock :: new ( RefCell :: new ( LineWriter :: with_capacity ( 0 ,  stdout_raw ( ) ) ) ) 
800+         ReentrantLock :: new ( RefCell :: new ( StdioBufWriter :: with_capacity ( 0 ,  stdout_raw ( ) ) ) ) 
731801    } ) ; 
732802
733803    if  !initialized { 
@@ -736,7 +806,7 @@ pub fn cleanup() {
736806        // might have leaked a StdoutLock, which would 
737807        // otherwise cause a deadlock here. 
738808        if  let  Some ( lock)  = stdout. try_lock ( )  { 
739-             * lock. borrow_mut ( )  = LineWriter :: with_capacity ( 0 ,  stdout_raw ( ) ) ; 
809+             * lock. borrow_mut ( )  = StdioBufWriter :: with_capacity ( 0 ,  stdout_raw ( ) ) ; 
740810        } 
741811    } 
742812} 
@@ -1262,7 +1332,18 @@ macro_rules! impl_is_terminal {
12621332    ) * } 
12631333} 
12641334
1265- impl_is_terminal ! ( File ,  Stdin ,  StdinLock <' _>,  Stdout ,  StdoutLock <' _>,  Stderr ,  StderrLock <' _>) ; 
1335+ impl_is_terminal ! ( 
1336+     File , 
1337+     Stdin , 
1338+     StdinLock <' _>, 
1339+     StdinRaw , 
1340+     Stdout , 
1341+     StdoutLock <' _>, 
1342+     StdoutRaw , 
1343+     Stderr , 
1344+     StderrLock <' _>, 
1345+     StderrRaw , 
1346+ ) ; 
12661347
12671348#[ unstable(  
12681349    feature = "print_internals" ,  
0 commit comments