@@ -5,7 +5,7 @@ use crate::io::prelude::*;
55use crate :: cell:: RefCell ;
66use crate :: fmt;
77use crate :: io:: lazy:: Lazy ;
8- use crate :: io:: { self , Initializer , BufReader , LineWriter , IoSlice , IoSliceMut } ;
8+ use crate :: io:: { self , Initializer , BufReader , BufWriter , LineWriter , IoSlice , IoSliceMut } ;
99use crate :: sync:: { Arc , Mutex , MutexGuard } ;
1010use crate :: sys:: stdio;
1111use crate :: sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
@@ -103,48 +103,31 @@ impl Write for StderrRaw {
103103 fn flush ( & mut self ) -> io:: Result < ( ) > { self . 0 . flush ( ) }
104104}
105105
106- enum Maybe < T > {
107- Real ( T ) ,
108- Fake ,
109- }
106+ /// Maps `EBADF` errors for reading and writing to success.
107+ struct HandleEbadf < T > ( T ) ;
110108
111- impl < W : io :: Write > io :: Write for Maybe < W > {
109+ impl < W : Write > Write for HandleEbadf < W > {
112110 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
113- match * self {
114- Maybe :: Real ( ref mut w) => handle_ebadf ( w. write ( buf) , buf. len ( ) ) ,
115- Maybe :: Fake => Ok ( buf. len ( ) )
116- }
111+ handle_ebadf ( self . 0 . write ( buf) , buf. len ( ) )
117112 }
118-
119113 fn write_vectored ( & mut self , bufs : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
120114 let total = bufs. iter ( ) . map ( |b| b. len ( ) ) . sum ( ) ;
121- match self {
122- Maybe :: Real ( w) => handle_ebadf ( w. write_vectored ( bufs) , total) ,
123- Maybe :: Fake => Ok ( total) ,
124- }
115+ handle_ebadf ( self . 0 . write_vectored ( bufs) , total)
125116 }
126-
127117 fn flush ( & mut self ) -> io:: Result < ( ) > {
128- match * self {
129- Maybe :: Real ( ref mut w) => handle_ebadf ( w. flush ( ) , ( ) ) ,
130- Maybe :: Fake => Ok ( ( ) )
131- }
118+ handle_ebadf ( self . 0 . flush ( ) , ( ) )
132119 }
133120}
134121
135- impl < R : io :: Read > io :: Read for Maybe < R > {
122+ impl < R : Read > Read for HandleEbadf < R > {
136123 fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
137- match * self {
138- Maybe :: Real ( ref mut r) => handle_ebadf ( r. read ( buf) , 0 ) ,
139- Maybe :: Fake => Ok ( 0 )
140- }
124+ handle_ebadf ( self . 0 . read ( buf) , 0 )
141125 }
142-
143126 fn read_vectored ( & mut self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> io:: Result < usize > {
144- match self {
145- Maybe :: Real ( r ) => handle_ebadf ( r . read_vectored ( bufs ) , 0 ) ,
146- Maybe :: Fake => Ok ( 0 )
147- }
127+ handle_ebadf ( self . 0 . read_vectored ( bufs ) , 0 )
128+ }
129+ unsafe fn initializer ( & self ) -> Initializer {
130+ self . 0 . initializer ( )
148131 }
149132}
150133
@@ -155,6 +138,121 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
155138 }
156139}
157140
141+ enum StdioBufferKind {
142+ LineBuffered ,
143+ Buffered ,
144+ Unbuffered ,
145+ }
146+
147+ /// A reader that can either be buffered or fake.
148+ ///
149+ /// If it is fake, all reads succeed and indicate end-of-file.
150+ enum StdioReader < R : Read > {
151+ Buffered ( BufReader < HandleEbadf < R > > ) ,
152+ Fake ,
153+ }
154+
155+ impl < R : Read > StdioReader < R > {
156+ fn new_buffered ( reader : R ) -> StdioReader < R > {
157+ let cap = stdio:: STDIN_BUF_SIZE ;
158+ StdioReader :: Buffered ( BufReader :: with_capacity ( cap, HandleEbadf ( reader) ) )
159+ }
160+ fn new_fake ( ) -> StdioReader < R > {
161+ StdioReader :: Fake
162+ }
163+ }
164+
165+ impl < R : Read > Read for StdioReader < R > {
166+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
167+ match self {
168+ StdioReader :: Buffered ( i) => i. read ( buf) ,
169+ StdioReader :: Fake => Ok ( 0 ) ,
170+ }
171+ }
172+ fn read_vectored ( & mut self , bufs : & mut [ io:: IoSliceMut < ' _ > ] ) -> io:: Result < usize > {
173+ match self {
174+ StdioReader :: Buffered ( i) => i. read_vectored ( bufs) ,
175+ StdioReader :: Fake => Ok ( 0 ) ,
176+ }
177+ }
178+ #[ inline]
179+ unsafe fn initializer ( & self ) -> Initializer {
180+ match self {
181+ StdioReader :: Buffered ( i) => i. initializer ( ) ,
182+ StdioReader :: Fake => Initializer :: nop ( ) ,
183+ }
184+ }
185+ }
186+
187+ impl < R : Read > BufRead for StdioReader < R > {
188+ fn fill_buf ( & mut self ) -> io:: Result < & [ u8 ] > {
189+ match self {
190+ StdioReader :: Buffered ( i) => i. fill_buf ( ) ,
191+ StdioReader :: Fake => Ok ( & [ ] ) ,
192+ }
193+ }
194+ fn consume ( & mut self , amt : usize ) {
195+ match self {
196+ StdioReader :: Buffered ( i) => i. consume ( amt) ,
197+ StdioReader :: Fake => ( ) ,
198+ }
199+ }
200+ }
201+
202+ /// A writer that can either be line-buffered, buffered, unbuffered or fake.
203+ ///
204+ /// If it is fake, all outputs just succeed and are dropped silently.
205+ enum StdioWriter < W : Write > {
206+ LineBuffered ( LineWriter < HandleEbadf < W > > ) ,
207+ Buffered ( BufWriter < HandleEbadf < W > > ) ,
208+ Unbuffered ( HandleEbadf < W > ) ,
209+ Fake ,
210+ }
211+
212+ impl < W : Write > StdioWriter < W > {
213+ fn new ( writer : W , kind : StdioBufferKind ) -> StdioWriter < W > {
214+ let writer = HandleEbadf ( writer) ;
215+ match kind {
216+ StdioBufferKind :: LineBuffered =>
217+ StdioWriter :: LineBuffered ( LineWriter :: new ( writer) ) ,
218+ StdioBufferKind :: Buffered =>
219+ StdioWriter :: Buffered ( BufWriter :: new ( writer) ) ,
220+ StdioBufferKind :: Unbuffered =>
221+ StdioWriter :: Unbuffered ( writer) ,
222+ }
223+ }
224+ fn new_fake ( ) -> StdioWriter < W > {
225+ StdioWriter :: Fake
226+ }
227+ }
228+
229+ impl < W : Write > Write for StdioWriter < W > {
230+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
231+ match self {
232+ StdioWriter :: LineBuffered ( i) => i. write ( buf) ,
233+ StdioWriter :: Buffered ( i) => i. write ( buf) ,
234+ StdioWriter :: Unbuffered ( i) => i. write ( buf) ,
235+ StdioWriter :: Fake => Ok ( buf. len ( ) ) ,
236+ }
237+ }
238+ fn write_vectored ( & mut self , bufs : & [ io:: IoSlice < ' _ > ] ) -> io:: Result < usize > {
239+ match self {
240+ StdioWriter :: LineBuffered ( i) => i. write_vectored ( bufs) ,
241+ StdioWriter :: Buffered ( i) => i. write_vectored ( bufs) ,
242+ StdioWriter :: Unbuffered ( i) => i. write_vectored ( bufs) ,
243+ StdioWriter :: Fake => Ok ( bufs. iter ( ) . map ( |b| b. len ( ) ) . sum ( ) ) ,
244+ }
245+ }
246+ fn flush ( & mut self ) -> io:: Result < ( ) > {
247+ match self {
248+ StdioWriter :: LineBuffered ( i) => i. flush ( ) ,
249+ StdioWriter :: Buffered ( i) => i. flush ( ) ,
250+ StdioWriter :: Unbuffered ( i) => i. flush ( ) ,
251+ StdioWriter :: Fake => Ok ( ( ) ) ,
252+ }
253+ }
254+ }
255+
158256/// A handle to the standard input stream of a process.
159257///
160258/// Each handle is a shared reference to a global buffer of input data to this
@@ -176,7 +274,7 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
176274/// an error.
177275#[ stable( feature = "rust1" , since = "1.0.0" ) ]
178276pub struct Stdin {
179- inner : Arc < Mutex < BufReader < Maybe < StdinRaw > > > > ,
277+ inner : Arc < Mutex < StdioReader < StdinRaw > > > ,
180278}
181279
182280/// A locked reference to the `Stdin` handle.
@@ -194,7 +292,7 @@ pub struct Stdin {
194292/// an error.
195293#[ stable( feature = "rust1" , since = "1.0.0" ) ]
196294pub struct StdinLock < ' a > {
197- inner : MutexGuard < ' a , BufReader < Maybe < StdinRaw > > > ,
295+ inner : MutexGuard < ' a , StdioReader < StdinRaw > > ,
198296}
199297
200298/// Constructs a new handle to the standard input of the current process.
@@ -240,21 +338,21 @@ pub struct StdinLock<'a> {
240338/// ```
241339#[ stable( feature = "rust1" , since = "1.0.0" ) ]
242340pub fn stdin ( ) -> Stdin {
243- static INSTANCE : Lazy < Mutex < BufReader < Maybe < StdinRaw > > > > = Lazy :: new ( ) ;
341+ static INSTANCE : Lazy < Mutex < StdioReader < StdinRaw > > > = Lazy :: new ( ) ;
244342 return Stdin {
245343 inner : unsafe {
246344 INSTANCE . get ( stdin_init) . expect ( "cannot access stdin during shutdown" )
247345 } ,
248346 } ;
249347
250- fn stdin_init ( ) -> Arc < Mutex < BufReader < Maybe < StdinRaw > > > > {
348+ fn stdin_init ( ) -> Arc < Mutex < StdioReader < StdinRaw > > > {
251349 // This must not reentrantly access `INSTANCE`
252350 let stdin = match stdin_raw ( ) {
253- Ok ( stdin) => Maybe :: Real ( stdin) ,
254- _ => Maybe :: Fake
351+ Ok ( stdin) => StdioReader :: new_buffered ( stdin) ,
352+ _ => StdioReader :: new_fake ( ) ,
255353 } ;
256354
257- Arc :: new ( Mutex :: new ( BufReader :: with_capacity ( stdio :: STDIN_BUF_SIZE , stdin) ) )
355+ Arc :: new ( Mutex :: new ( stdin) )
258356 }
259357}
260358
@@ -401,7 +499,7 @@ pub struct Stdout {
401499 // FIXME: this should be LineWriter or BufWriter depending on the state of
402500 // stdout (tty or not). Note that if this is not line buffered it
403501 // should also flush-on-panic or some form of flush-on-abort.
404- inner : Arc < ReentrantMutex < RefCell < LineWriter < Maybe < StdoutRaw > > > > > ,
502+ inner : Arc < ReentrantMutex < RefCell < StdioWriter < StdoutRaw > > > > ,
405503}
406504
407505/// A locked reference to the `Stdout` handle.
@@ -418,7 +516,7 @@ pub struct Stdout {
418516/// [`Stdout::lock`]: struct.Stdout.html#method.lock
419517#[ stable( feature = "rust1" , since = "1.0.0" ) ]
420518pub struct StdoutLock < ' a > {
421- inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < Maybe < StdoutRaw > > > > ,
519+ inner : ReentrantMutexGuard < ' a , RefCell < StdioWriter < StdoutRaw > > > ,
422520}
423521
424522/// Constructs a new handle to the standard output of the current process.
@@ -464,20 +562,20 @@ pub struct StdoutLock<'a> {
464562/// ```
465563#[ stable( feature = "rust1" , since = "1.0.0" ) ]
466564pub fn stdout ( ) -> Stdout {
467- static INSTANCE : Lazy < ReentrantMutex < RefCell < LineWriter < Maybe < StdoutRaw > > > > > = Lazy :: new ( ) ;
565+ static INSTANCE : Lazy < ReentrantMutex < RefCell < StdioWriter < StdoutRaw > > > > = Lazy :: new ( ) ;
468566 return Stdout {
469567 inner : unsafe {
470568 INSTANCE . get ( stdout_init) . expect ( "cannot access stdout during shutdown" )
471569 } ,
472570 } ;
473571
474- fn stdout_init ( ) -> Arc < ReentrantMutex < RefCell < LineWriter < Maybe < StdoutRaw > > > > > {
572+ fn stdout_init ( ) -> Arc < ReentrantMutex < RefCell < StdioWriter < StdoutRaw > > > > {
475573 // This must not reentrantly access `INSTANCE`
476574 let stdout = match stdout_raw ( ) {
477- Ok ( stdout) => Maybe :: Real ( stdout) ,
478- _ => Maybe :: Fake ,
575+ Ok ( stdout) => StdioWriter :: new ( stdout, StdioBufferKind :: LineBuffered ) ,
576+ _ => StdioWriter :: new_fake ( ) ,
479577 } ;
480- Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( LineWriter :: new ( stdout) ) ) )
578+ Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( stdout) ) )
481579 }
482580}
483581
@@ -565,7 +663,7 @@ impl fmt::Debug for StdoutLock<'_> {
565663/// an error.
566664#[ stable( feature = "rust1" , since = "1.0.0" ) ]
567665pub struct Stderr {
568- inner : Arc < ReentrantMutex < RefCell < Maybe < StderrRaw > > > > ,
666+ inner : Arc < ReentrantMutex < RefCell < StdioWriter < StderrRaw > > > > ,
569667}
570668
571669/// A locked reference to the `Stderr` handle.
@@ -581,7 +679,7 @@ pub struct Stderr {
581679/// an error.
582680#[ stable( feature = "rust1" , since = "1.0.0" ) ]
583681pub struct StderrLock < ' a > {
584- inner : ReentrantMutexGuard < ' a , RefCell < Maybe < StderrRaw > > > ,
682+ inner : ReentrantMutexGuard < ' a , RefCell < StdioWriter < StderrRaw > > > ,
585683}
586684
587685/// Constructs a new handle to the standard error of the current process.
@@ -623,18 +721,18 @@ pub struct StderrLock<'a> {
623721/// ```
624722#[ stable( feature = "rust1" , since = "1.0.0" ) ]
625723pub fn stderr ( ) -> Stderr {
626- static INSTANCE : Lazy < ReentrantMutex < RefCell < Maybe < StderrRaw > > > > = Lazy :: new ( ) ;
724+ static INSTANCE : Lazy < ReentrantMutex < RefCell < StdioWriter < StderrRaw > > > > = Lazy :: new ( ) ;
627725 return Stderr {
628726 inner : unsafe {
629727 INSTANCE . get ( stderr_init) . expect ( "cannot access stderr during shutdown" )
630728 } ,
631729 } ;
632730
633- fn stderr_init ( ) -> Arc < ReentrantMutex < RefCell < Maybe < StderrRaw > > > > {
731+ fn stderr_init ( ) -> Arc < ReentrantMutex < RefCell < StdioWriter < StderrRaw > > > > {
634732 // This must not reentrantly access `INSTANCE`
635733 let stderr = match stderr_raw ( ) {
636- Ok ( stderr) => Maybe :: Real ( stderr) ,
637- _ => Maybe :: Fake ,
734+ Ok ( stderr) => StdioWriter :: new ( stderr, StdioBufferKind :: Unbuffered ) ,
735+ _ => StdioWriter :: new_fake ( ) ,
638736 } ;
639737 Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( stderr) ) )
640738 }
0 commit comments