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