]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/stdio.rs
Rollup merge of #65647 - nnethercote:rm-unnecessary-traits, r=Centril
[rust.git] / src / libstd / io / stdio.rs
1 #![cfg_attr(test, allow(unused))]
2
3 use crate::io::prelude::*;
4
5 use crate::cell::RefCell;
6 use crate::fmt;
7 use crate::io::lazy::Lazy;
8 use crate::io::{self, Initializer, BufReader, LineWriter, IoSlice, IoSliceMut};
9 use crate::sync::{Arc, Mutex, MutexGuard};
10 use crate::sys::stdio;
11 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
12 use crate::thread::LocalKey;
13
14 thread_local! {
15     /// Stdout used by print! and println! macros
16     static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
17         RefCell::new(None)
18     }
19 }
20
21 thread_local! {
22     /// Stderr used by eprint! and eprintln! macros, and panics
23     static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
24         RefCell::new(None)
25     }
26 }
27
28 /// A handle to a raw instance of the standard input stream of this process.
29 ///
30 /// This handle is not synchronized or buffered in any fashion. Constructed via
31 /// the `std::io::stdio::stdin_raw` function.
32 struct StdinRaw(stdio::Stdin);
33
34 /// A handle to a raw instance of the standard output stream of this process.
35 ///
36 /// This handle is not synchronized or buffered in any fashion. Constructed via
37 /// the `std::io::stdio::stdout_raw` function.
38 struct StdoutRaw(stdio::Stdout);
39
40 /// A handle to a raw instance of the standard output stream of this process.
41 ///
42 /// This handle is not synchronized or buffered in any fashion. Constructed via
43 /// the `std::io::stdio::stderr_raw` function.
44 struct StderrRaw(stdio::Stderr);
45
46 /// Constructs a new raw handle to the standard input of this process.
47 ///
48 /// The returned handle does not interact with any other handles created nor
49 /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
50 /// handles is **not** available to raw handles returned from this function.
51 ///
52 /// The returned handle has no external synchronization or buffering.
53 fn stdin_raw() -> io::Result<StdinRaw> { stdio::Stdin::new().map(StdinRaw) }
54
55 /// Constructs a new raw handle to the standard output stream of this process.
56 ///
57 /// The returned handle does not interact with any other handles created nor
58 /// handles returned by `std::io::stdout`. Note that data is buffered by the
59 /// `std::io::stdout` handles so writes which happen via this raw handle may
60 /// appear before previous writes.
61 ///
62 /// The returned handle has no external synchronization or buffering layered on
63 /// top.
64 fn stdout_raw() -> io::Result<StdoutRaw> { stdio::Stdout::new().map(StdoutRaw) }
65
66 /// Constructs a new raw handle to the standard error stream of this process.
67 ///
68 /// The returned handle does not interact with any other handles created nor
69 /// handles returned by `std::io::stderr`.
70 ///
71 /// The returned handle has no external synchronization or buffering layered on
72 /// top.
73 fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }
74
75 impl Read for StdinRaw {
76     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
77
78     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
79         self.0.read_vectored(bufs)
80     }
81
82     #[inline]
83     unsafe fn initializer(&self) -> Initializer {
84         Initializer::nop()
85     }
86 }
87 impl Write for StdoutRaw {
88     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
89
90     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
91         self.0.write_vectored(bufs)
92     }
93
94     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
95 }
96 impl Write for StderrRaw {
97     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
98
99     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
100         self.0.write_vectored(bufs)
101     }
102
103     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
104 }
105
106 enum Maybe<T> {
107     Real(T),
108     Fake,
109 }
110
111 impl<W: io::Write> io::Write for Maybe<W> {
112     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         }
117     }
118
119     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
120         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         }
125     }
126
127     fn flush(&mut self) -> io::Result<()> {
128         match *self {
129             Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
130             Maybe::Fake => Ok(())
131         }
132     }
133 }
134
135 impl<R: io::Read> io::Read for Maybe<R> {
136     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         }
141     }
142
143     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         }
148     }
149 }
150
151 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
152     match r {
153         Err(ref e) if stdio::is_ebadf(e) => Ok(default),
154         r => r
155     }
156 }
157
158 /// A handle to the standard input stream of a process.
159 ///
160 /// Each handle is a shared reference to a global buffer of input data to this
161 /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
162 /// (e.g., `.lines()`). Reads to this handle are otherwise locked with respect
163 /// to other reads.
164 ///
165 /// This handle implements the `Read` trait, but beware that concurrent reads
166 /// of `Stdin` must be executed with care.
167 ///
168 /// Created by the [`io::stdin`] method.
169 ///
170 /// [`io::stdin`]: fn.stdin.html
171 /// [`BufRead`]: trait.BufRead.html
172 ///
173 /// ### Note: Windows Portability Consideration
174 /// When operating in a console, the Windows implementation of this stream does not support
175 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
176 /// an error.
177 #[stable(feature = "rust1", since = "1.0.0")]
178 pub struct Stdin {
179     inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
180 }
181
182 /// A locked reference to the `Stdin` handle.
183 ///
184 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
185 /// is constructed via the [`Stdin::lock`] method.
186 ///
187 /// [`Read`]: trait.Read.html
188 /// [`BufRead`]: trait.BufRead.html
189 /// [`Stdin::lock`]: struct.Stdin.html#method.lock
190 ///
191 /// ### Note: Windows Portability Consideration
192 /// When operating in a console, the Windows implementation of this stream does not support
193 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
194 /// an error.
195 #[stable(feature = "rust1", since = "1.0.0")]
196 pub struct StdinLock<'a> {
197     inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
198 }
199
200 /// Constructs a new handle to the standard input of the current process.
201 ///
202 /// Each handle returned is a reference to a shared global buffer whose access
203 /// is synchronized via a mutex. If you need more explicit control over
204 /// locking, see the [`Stdin::lock`] method.
205 ///
206 /// [`Stdin::lock`]: struct.Stdin.html#method.lock
207 ///
208 /// ### Note: Windows Portability Consideration
209 /// When operating in a console, the Windows implementation of this stream does not support
210 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
211 /// an error.
212 ///
213 /// # Examples
214 ///
215 /// Using implicit synchronization:
216 ///
217 /// ```no_run
218 /// use std::io::{self, Read};
219 ///
220 /// fn main() -> io::Result<()> {
221 ///     let mut buffer = String::new();
222 ///     io::stdin().read_to_string(&mut buffer)?;
223 ///     Ok(())
224 /// }
225 /// ```
226 ///
227 /// Using explicit synchronization:
228 ///
229 /// ```no_run
230 /// use std::io::{self, Read};
231 ///
232 /// fn main() -> io::Result<()> {
233 ///     let mut buffer = String::new();
234 ///     let stdin = io::stdin();
235 ///     let mut handle = stdin.lock();
236 ///
237 ///     handle.read_to_string(&mut buffer)?;
238 ///     Ok(())
239 /// }
240 /// ```
241 #[stable(feature = "rust1", since = "1.0.0")]
242 pub fn stdin() -> Stdin {
243     static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
244     return Stdin {
245         inner: unsafe {
246             INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown")
247         },
248     };
249
250     fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
251         // This must not reentrantly access `INSTANCE`
252         let stdin = match stdin_raw() {
253             Ok(stdin) => Maybe::Real(stdin),
254             _ => Maybe::Fake
255         };
256
257         Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin)))
258     }
259 }
260
261 impl Stdin {
262     /// Locks this handle to the standard input stream, returning a readable
263     /// guard.
264     ///
265     /// The lock is released when the returned lock goes out of scope. The
266     /// returned guard also implements the [`Read`] and [`BufRead`] traits for
267     /// accessing the underlying data.
268     ///
269     /// [`Read`]: trait.Read.html
270     /// [`BufRead`]: trait.BufRead.html
271     ///
272     /// # Examples
273     ///
274     /// ```no_run
275     /// use std::io::{self, Read};
276     ///
277     /// fn main() -> io::Result<()> {
278     ///     let mut buffer = String::new();
279     ///     let stdin = io::stdin();
280     ///     let mut handle = stdin.lock();
281     ///
282     ///     handle.read_to_string(&mut buffer)?;
283     ///     Ok(())
284     /// }
285     /// ```
286     #[stable(feature = "rust1", since = "1.0.0")]
287     pub fn lock(&self) -> StdinLock<'_> {
288         StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
289     }
290
291     /// Locks this handle and reads a line of input into the specified buffer.
292     ///
293     /// For detailed semantics of this method, see the documentation on
294     /// [`BufRead::read_line`].
295     ///
296     /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
297     ///
298     /// # Examples
299     ///
300     /// ```no_run
301     /// use std::io;
302     ///
303     /// let mut input = String::new();
304     /// match io::stdin().read_line(&mut input) {
305     ///     Ok(n) => {
306     ///         println!("{} bytes read", n);
307     ///         println!("{}", input);
308     ///     }
309     ///     Err(error) => println!("error: {}", error),
310     /// }
311     /// ```
312     ///
313     /// You can run the example one of two ways:
314     ///
315     /// - Pipe some text to it, e.g., `printf foo | path/to/executable`
316     /// - Give it text interactively by running the executable directly,
317     ///   in which case it will wait for the Enter key to be pressed before
318     ///   continuing
319     #[stable(feature = "rust1", since = "1.0.0")]
320     pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
321         self.lock().read_line(buf)
322     }
323 }
324
325 #[stable(feature = "std_debug", since = "1.16.0")]
326 impl fmt::Debug for Stdin {
327     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328         f.pad("Stdin { .. }")
329     }
330 }
331
332 #[stable(feature = "rust1", since = "1.0.0")]
333 impl Read for Stdin {
334     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
335         self.lock().read(buf)
336     }
337     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
338         self.lock().read_vectored(bufs)
339     }
340     #[inline]
341     unsafe fn initializer(&self) -> Initializer {
342         Initializer::nop()
343     }
344     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
345         self.lock().read_to_end(buf)
346     }
347     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
348         self.lock().read_to_string(buf)
349     }
350     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
351         self.lock().read_exact(buf)
352     }
353 }
354
355 #[stable(feature = "rust1", since = "1.0.0")]
356 impl Read for StdinLock<'_> {
357     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
358         self.inner.read(buf)
359     }
360
361     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
362         self.inner.read_vectored(bufs)
363     }
364
365     #[inline]
366     unsafe fn initializer(&self) -> Initializer {
367         Initializer::nop()
368     }
369 }
370
371 #[stable(feature = "rust1", since = "1.0.0")]
372 impl BufRead for StdinLock<'_> {
373     fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
374     fn consume(&mut self, n: usize) { self.inner.consume(n) }
375 }
376
377 #[stable(feature = "std_debug", since = "1.16.0")]
378 impl fmt::Debug for StdinLock<'_> {
379     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380         f.pad("StdinLock { .. }")
381     }
382 }
383
384 /// A handle to the global standard output stream of the current process.
385 ///
386 /// Each handle shares a global buffer of data to be written to the standard
387 /// output stream. Access is also synchronized via a lock and explicit control
388 /// over locking is available via the [`lock`] method.
389 ///
390 /// Created by the [`io::stdout`] method.
391 ///
392 /// ### Note: Windows Portability Consideration
393 /// When operating in a console, the Windows implementation of this stream does not support
394 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
395 /// an error.
396 ///
397 /// [`lock`]: #method.lock
398 /// [`io::stdout`]: fn.stdout.html
399 #[stable(feature = "rust1", since = "1.0.0")]
400 pub struct Stdout {
401     // FIXME: this should be LineWriter or BufWriter depending on the state of
402     //        stdout (tty or not). Note that if this is not line buffered it
403     //        should also flush-on-panic or some form of flush-on-abort.
404     inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
405 }
406
407 /// A locked reference to the `Stdout` handle.
408 ///
409 /// This handle implements the [`Write`] trait, and is constructed via
410 /// the [`Stdout::lock`] method.
411 ///
412 /// ### Note: Windows Portability Consideration
413 /// When operating in a console, the Windows implementation of this stream does not support
414 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
415 /// an error.
416 ///
417 /// [`Write`]: trait.Write.html
418 /// [`Stdout::lock`]: struct.Stdout.html#method.lock
419 #[stable(feature = "rust1", since = "1.0.0")]
420 pub struct StdoutLock<'a> {
421     inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
422 }
423
424 /// Constructs a new handle to the standard output of the current process.
425 ///
426 /// Each handle returned is a reference to a shared global buffer whose access
427 /// is synchronized via a mutex. If you need more explicit control over
428 /// locking, see the [`Stdout::lock`] method.
429 ///
430 /// [`Stdout::lock`]: struct.Stdout.html#method.lock
431 ///
432 /// ### Note: Windows Portability Consideration
433 /// When operating in a console, the Windows implementation of this stream does not support
434 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
435 /// an error.
436 ///
437 /// # Examples
438 ///
439 /// Using implicit synchronization:
440 ///
441 /// ```no_run
442 /// use std::io::{self, Write};
443 ///
444 /// fn main() -> io::Result<()> {
445 ///     io::stdout().write_all(b"hello world")?;
446 ///
447 ///     Ok(())
448 /// }
449 /// ```
450 ///
451 /// Using explicit synchronization:
452 ///
453 /// ```no_run
454 /// use std::io::{self, Write};
455 ///
456 /// fn main() -> io::Result<()> {
457 ///     let stdout = io::stdout();
458 ///     let mut handle = stdout.lock();
459 ///
460 ///     handle.write_all(b"hello world")?;
461 ///
462 ///     Ok(())
463 /// }
464 /// ```
465 #[stable(feature = "rust1", since = "1.0.0")]
466 pub fn stdout() -> Stdout {
467     static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
468     return Stdout {
469         inner: unsafe {
470             INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown")
471         },
472     };
473
474     fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
475         // This must not reentrantly access `INSTANCE`
476         let stdout = match stdout_raw() {
477             Ok(stdout) => Maybe::Real(stdout),
478             _ => Maybe::Fake,
479         };
480         Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))))
481     }
482 }
483
484 impl Stdout {
485     /// Locks this handle to the standard output stream, returning a writable
486     /// guard.
487     ///
488     /// The lock is released when the returned lock goes out of scope. The
489     /// returned guard also implements the `Write` trait for writing data.
490     ///
491     /// # Examples
492     ///
493     /// ```no_run
494     /// use std::io::{self, Write};
495     ///
496     /// fn main() -> io::Result<()> {
497     ///     let stdout = io::stdout();
498     ///     let mut handle = stdout.lock();
499     ///
500     ///     handle.write_all(b"hello world")?;
501     ///
502     ///     Ok(())
503     /// }
504     /// ```
505     #[stable(feature = "rust1", since = "1.0.0")]
506     pub fn lock(&self) -> StdoutLock<'_> {
507         StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
508     }
509 }
510
511 #[stable(feature = "std_debug", since = "1.16.0")]
512 impl fmt::Debug for Stdout {
513     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514         f.pad("Stdout { .. }")
515     }
516 }
517
518 #[stable(feature = "rust1", since = "1.0.0")]
519 impl Write for Stdout {
520     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
521         self.lock().write(buf)
522     }
523     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
524         self.lock().write_vectored(bufs)
525     }
526     fn flush(&mut self) -> io::Result<()> {
527         self.lock().flush()
528     }
529     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
530         self.lock().write_all(buf)
531     }
532     fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
533         self.lock().write_fmt(args)
534     }
535 }
536 #[stable(feature = "rust1", since = "1.0.0")]
537 impl Write for StdoutLock<'_> {
538     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
539         self.inner.borrow_mut().write(buf)
540     }
541     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
542         self.inner.borrow_mut().write_vectored(bufs)
543     }
544     fn flush(&mut self) -> io::Result<()> {
545         self.inner.borrow_mut().flush()
546     }
547 }
548
549 #[stable(feature = "std_debug", since = "1.16.0")]
550 impl fmt::Debug for StdoutLock<'_> {
551     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
552         f.pad("StdoutLock { .. }")
553     }
554 }
555
556 /// A handle to the standard error stream of a process.
557 ///
558 /// For more information, see the [`io::stderr`] method.
559 ///
560 /// [`io::stderr`]: fn.stderr.html
561 ///
562 /// ### Note: Windows Portability Consideration
563 /// When operating in a console, the Windows implementation of this stream does not support
564 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
565 /// an error.
566 #[stable(feature = "rust1", since = "1.0.0")]
567 pub struct Stderr {
568     inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>,
569 }
570
571 /// A locked reference to the `Stderr` handle.
572 ///
573 /// This handle implements the `Write` trait and is constructed via
574 /// the [`Stderr::lock`] method.
575 ///
576 /// [`Stderr::lock`]: struct.Stderr.html#method.lock
577 ///
578 /// ### Note: Windows Portability Consideration
579 /// When operating in a console, the Windows implementation of this stream does not support
580 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
581 /// an error.
582 #[stable(feature = "rust1", since = "1.0.0")]
583 pub struct StderrLock<'a> {
584     inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
585 }
586
587 /// Constructs a new handle to the standard error of the current process.
588 ///
589 /// This handle is not buffered.
590 ///
591 /// ### Note: Windows Portability Consideration
592 /// When operating in a console, the Windows implementation of this stream does not support
593 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
594 /// an error.
595 ///
596 /// # Examples
597 ///
598 /// Using implicit synchronization:
599 ///
600 /// ```no_run
601 /// use std::io::{self, Write};
602 ///
603 /// fn main() -> io::Result<()> {
604 ///     io::stderr().write_all(b"hello world")?;
605 ///
606 ///     Ok(())
607 /// }
608 /// ```
609 ///
610 /// Using explicit synchronization:
611 ///
612 /// ```no_run
613 /// use std::io::{self, Write};
614 ///
615 /// fn main() -> io::Result<()> {
616 ///     let stderr = io::stderr();
617 ///     let mut handle = stderr.lock();
618 ///
619 ///     handle.write_all(b"hello world")?;
620 ///
621 ///     Ok(())
622 /// }
623 /// ```
624 #[stable(feature = "rust1", since = "1.0.0")]
625 pub fn stderr() -> Stderr {
626     static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new();
627     return Stderr {
628         inner: unsafe {
629             INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown")
630         },
631     };
632
633     fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
634         // This must not reentrantly access `INSTANCE`
635         let stderr = match stderr_raw() {
636             Ok(stderr) => Maybe::Real(stderr),
637             _ => Maybe::Fake,
638         };
639         Arc::new(ReentrantMutex::new(RefCell::new(stderr)))
640     }
641 }
642
643 impl Stderr {
644     /// Locks this handle to the standard error stream, returning a writable
645     /// guard.
646     ///
647     /// The lock is released when the returned lock goes out of scope. The
648     /// returned guard also implements the `Write` trait for writing data.
649     ///
650     /// # Examples
651     ///
652     /// ```
653     /// use std::io::{self, Write};
654     ///
655     /// fn foo() -> io::Result<()> {
656     ///     let stderr = io::stderr();
657     ///     let mut handle = stderr.lock();
658     ///
659     ///     handle.write_all(b"hello world")?;
660     ///
661     ///     Ok(())
662     /// }
663     /// ```
664     #[stable(feature = "rust1", since = "1.0.0")]
665     pub fn lock(&self) -> StderrLock<'_> {
666         StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
667     }
668 }
669
670 #[stable(feature = "std_debug", since = "1.16.0")]
671 impl fmt::Debug for Stderr {
672     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
673         f.pad("Stderr { .. }")
674     }
675 }
676
677 #[stable(feature = "rust1", since = "1.0.0")]
678 impl Write for Stderr {
679     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
680         self.lock().write(buf)
681     }
682     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
683         self.lock().write_vectored(bufs)
684     }
685     fn flush(&mut self) -> io::Result<()> {
686         self.lock().flush()
687     }
688     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
689         self.lock().write_all(buf)
690     }
691     fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
692         self.lock().write_fmt(args)
693     }
694 }
695 #[stable(feature = "rust1", since = "1.0.0")]
696 impl Write for StderrLock<'_> {
697     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
698         self.inner.borrow_mut().write(buf)
699     }
700     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
701         self.inner.borrow_mut().write_vectored(bufs)
702     }
703     fn flush(&mut self) -> io::Result<()> {
704         self.inner.borrow_mut().flush()
705     }
706 }
707
708 #[stable(feature = "std_debug", since = "1.16.0")]
709 impl fmt::Debug for StderrLock<'_> {
710     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
711         f.pad("StderrLock { .. }")
712     }
713 }
714
715 /// Resets the thread-local stderr handle to the specified writer
716 ///
717 /// This will replace the current thread's stderr handle, returning the old
718 /// handle. All future calls to `panic!` and friends will emit their output to
719 /// this specified handle.
720 ///
721 /// Note that this does not need to be called for all new threads; the default
722 /// output handle is to the process's stderr stream.
723 #[unstable(feature = "set_stdio",
724            reason = "this function may disappear completely or be replaced \
725                      with a more general mechanism",
726            issue = "0")]
727 #[doc(hidden)]
728 pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
729     use crate::mem;
730     LOCAL_STDERR.with(move |slot| {
731         mem::replace(&mut *slot.borrow_mut(), sink)
732     }).and_then(|mut s| {
733         let _ = s.flush();
734         Some(s)
735     })
736 }
737
738 /// Resets the thread-local stdout handle to the specified writer
739 ///
740 /// This will replace the current thread's stdout handle, returning the old
741 /// handle. All future calls to `print!` and friends will emit their output to
742 /// this specified handle.
743 ///
744 /// Note that this does not need to be called for all new threads; the default
745 /// output handle is to the process's stdout stream.
746 #[unstable(feature = "set_stdio",
747            reason = "this function may disappear completely or be replaced \
748                      with a more general mechanism",
749            issue = "0")]
750 #[doc(hidden)]
751 pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
752     use crate::mem;
753     LOCAL_STDOUT.with(move |slot| {
754         mem::replace(&mut *slot.borrow_mut(), sink)
755     }).and_then(|mut s| {
756         let _ = s.flush();
757         Some(s)
758     })
759 }
760
761 /// Write `args` to output stream `local_s` if possible, `global_s`
762 /// otherwise. `label` identifies the stream in a panic message.
763 ///
764 /// This function is used to print error messages, so it takes extra
765 /// care to avoid causing a panic when `local_s` is unusable.
766 /// For instance, if the TLS key for the local stream is
767 /// already destroyed, or if the local stream is locked by another
768 /// thread, it will just fall back to the global stream.
769 ///
770 /// However, if the actual I/O causes an error, this function does panic.
771 fn print_to<T>(
772     args: fmt::Arguments<'_>,
773     local_s: &'static LocalKey<RefCell<Option<Box<dyn Write+Send>>>>,
774     global_s: fn() -> T,
775     label: &str,
776 )
777 where
778     T: Write,
779 {
780     let result = local_s.try_with(|s| {
781         if let Ok(mut borrowed) = s.try_borrow_mut() {
782             if let Some(w) = borrowed.as_mut() {
783                 return w.write_fmt(args);
784             }
785         }
786         global_s().write_fmt(args)
787     }).unwrap_or_else(|_| {
788         global_s().write_fmt(args)
789     });
790
791     if let Err(e) = result {
792         panic!("failed printing to {}: {}", label, e);
793     }
794 }
795
796 #[unstable(feature = "print_internals",
797            reason = "implementation detail which may disappear or be replaced at any time",
798            issue = "0")]
799 #[doc(hidden)]
800 #[cfg(not(test))]
801 pub fn _print(args: fmt::Arguments<'_>) {
802     print_to(args, &LOCAL_STDOUT, stdout, "stdout");
803 }
804
805 #[unstable(feature = "print_internals",
806            reason = "implementation detail which may disappear or be replaced at any time",
807            issue = "0")]
808 #[doc(hidden)]
809 #[cfg(not(test))]
810 pub fn _eprint(args: fmt::Arguments<'_>) {
811     print_to(args, &LOCAL_STDERR, stderr, "stderr");
812 }
813
814 #[cfg(test)]
815 pub use realstd::io::{_eprint, _print};
816
817 #[cfg(test)]
818 mod tests {
819     use crate::panic::{UnwindSafe, RefUnwindSafe};
820     use crate::thread;
821     use super::*;
822
823     #[test]
824     fn stdout_unwind_safe() {
825         assert_unwind_safe::<Stdout>();
826     }
827     #[test]
828     fn stdoutlock_unwind_safe() {
829         assert_unwind_safe::<StdoutLock<'_>>();
830         assert_unwind_safe::<StdoutLock<'static>>();
831     }
832     #[test]
833     fn stderr_unwind_safe() {
834         assert_unwind_safe::<Stderr>();
835     }
836     #[test]
837     fn stderrlock_unwind_safe() {
838         assert_unwind_safe::<StderrLock<'_>>();
839         assert_unwind_safe::<StderrLock<'static>>();
840     }
841
842     fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
843
844     #[test]
845     #[cfg_attr(target_os = "emscripten", ignore)]
846     fn panic_doesnt_poison() {
847         thread::spawn(|| {
848             let _a = stdin();
849             let _a = _a.lock();
850             let _a = stdout();
851             let _a = _a.lock();
852             let _a = stderr();
853             let _a = _a.lock();
854             panic!();
855         }).join().unwrap_err();
856
857         let _a = stdin();
858         let _a = _a.lock();
859         let _a = stdout();
860         let _a = _a.lock();
861         let _a = stderr();
862         let _a = _a.lock();
863     }
864 }