1 #![cfg_attr(test, allow(unused))]
6 use crate::io
::prelude
::*;
8 use crate::cell
::{Cell, RefCell}
;
10 use crate::io
::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter}
;
11 use crate::lazy
::SyncOnceCell
;
13 use crate::sync
::atomic
::{AtomicBool, Ordering}
;
14 use crate::sync
::{Arc, Mutex, MutexGuard}
;
15 use crate::sys
::stdio
;
16 use crate::sys_common
;
17 use crate::sys_common
::remutex
::{ReentrantMutex, ReentrantMutexGuard}
;
19 type LocalStream
= Arc
<Mutex
<Vec
<u8>>>;
22 /// Used by the test crate to capture the output of the print macros and panics.
23 static OUTPUT_CAPTURE
: Cell
<Option
<LocalStream
>> = {
28 /// Flag to indicate OUTPUT_CAPTURE is used.
30 /// If it is None and was never set on any thread, this flag is set to false,
31 /// and OUTPUT_CAPTURE can be safely ignored on all threads, saving some time
32 /// and memory registering an unused thread local.
34 /// Note about memory ordering: This contains information about whether a
35 /// thread local variable might be in use. Although this is a global flag, the
36 /// memory ordering between threads does not matter: we only want this flag to
37 /// have a consistent order between set_output_capture and print_to *within
38 /// the same thread*. Within the same thread, things always have a perfectly
39 /// consistent order. So Ordering::Relaxed is fine.
40 static OUTPUT_CAPTURE_USED
: AtomicBool
= AtomicBool
::new(false);
42 /// A handle to a raw instance of the standard input stream of this process.
44 /// This handle is not synchronized or buffered in any fashion. Constructed via
45 /// the `std::io::stdio::stdin_raw` function.
46 struct StdinRaw(stdio
::Stdin
);
48 /// A handle to a raw instance of the standard output stream of this process.
50 /// This handle is not synchronized or buffered in any fashion. Constructed via
51 /// the `std::io::stdio::stdout_raw` function.
52 struct StdoutRaw(stdio
::Stdout
);
54 /// A handle to a raw instance of the standard output stream of this process.
56 /// This handle is not synchronized or buffered in any fashion. Constructed via
57 /// the `std::io::stdio::stderr_raw` function.
58 struct StderrRaw(stdio
::Stderr
);
60 /// Constructs a new raw handle to the standard input of this process.
62 /// The returned handle does not interact with any other handles created nor
63 /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
64 /// handles is **not** available to raw handles returned from this function.
66 /// The returned handle has no external synchronization or buffering.
67 #[unstable(feature = "libstd_sys_internals", issue = "none")]
68 const fn stdin_raw() -> StdinRaw
{
69 StdinRaw(stdio
::Stdin
::new())
72 /// Constructs a new raw handle to the standard output stream of this process.
74 /// The returned handle does not interact with any other handles created nor
75 /// handles returned by `std::io::stdout`. Note that data is buffered by the
76 /// `std::io::stdout` handles so writes which happen via this raw handle may
77 /// appear before previous writes.
79 /// The returned handle has no external synchronization or buffering layered on
81 #[unstable(feature = "libstd_sys_internals", issue = "none")]
82 const fn stdout_raw() -> StdoutRaw
{
83 StdoutRaw(stdio
::Stdout
::new())
86 /// Constructs a new raw handle to the standard error stream of this process.
88 /// The returned handle does not interact with any other handles created nor
89 /// handles returned by `std::io::stderr`.
91 /// The returned handle has no external synchronization or buffering layered on
93 #[unstable(feature = "libstd_sys_internals", issue = "none")]
94 const fn stderr_raw() -> StderrRaw
{
95 StderrRaw(stdio
::Stderr
::new())
98 impl Read
for StdinRaw
{
99 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
100 handle_ebadf(self.0.read(buf
), 0)
103 fn read_vectored(&mut self, bufs
: &mut [IoSliceMut
<'_
>]) -> io
::Result
<usize> {
104 handle_ebadf(self.0.read_vectored(bufs
), 0)
108 fn is_read_vectored(&self) -> bool
{
109 self.0.is_read_vectored
()
113 unsafe fn initializer(&self) -> Initializer
{
117 fn read_to_end(&mut self, buf
: &mut Vec
<u8>) -> io
::Result
<usize> {
118 handle_ebadf(self.0.read_to_end(buf
), 0)
121 fn read_to_string(&mut self, buf
: &mut String
) -> io
::Result
<usize> {
122 handle_ebadf(self.0.read_to_string(buf
), 0)
126 impl Write
for StdoutRaw
{
127 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
128 handle_ebadf(self.0.write(buf
), buf
.len())
131 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
132 let total
= bufs
.iter().map(|b
| b
.len()).sum();
133 handle_ebadf(self.0.write_vectored(bufs
), total
)
137 fn is_write_vectored(&self) -> bool
{
138 self.0.is_write_vectored
()
141 fn flush(&mut self) -> io
::Result
<()> {
142 handle_ebadf(self.0.flush
(), ())
145 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
146 handle_ebadf(self.0.write_all(buf
), ())
149 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
150 handle_ebadf(self.0.write_all_vectored(bufs
), ())
153 fn write_fmt(&mut self, fmt
: fmt
::Arguments
<'_
>) -> io
::Result
<()> {
154 handle_ebadf(self.0.write_fmt(fmt
), ())
158 impl Write
for StderrRaw
{
159 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
160 handle_ebadf(self.0.write(buf
), buf
.len())
163 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
164 let total
= bufs
.iter().map(|b
| b
.len()).sum();
165 handle_ebadf(self.0.write_vectored(bufs
), total
)
169 fn is_write_vectored(&self) -> bool
{
170 self.0.is_write_vectored
()
173 fn flush(&mut self) -> io
::Result
<()> {
174 handle_ebadf(self.0.flush
(), ())
177 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
178 handle_ebadf(self.0.write_all(buf
), ())
181 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
182 handle_ebadf(self.0.write_all_vectored(bufs
), ())
185 fn write_fmt(&mut self, fmt
: fmt
::Arguments
<'_
>) -> io
::Result
<()> {
186 handle_ebadf(self.0.write_fmt(fmt
), ())
190 fn handle_ebadf
<T
>(r
: io
::Result
<T
>, default: T
) -> io
::Result
<T
> {
192 Err(ref e
) if stdio
::is_ebadf(e
) => Ok(default),
197 /// A handle to the standard input stream of a process.
199 /// Each handle is a shared reference to a global buffer of input data to this
200 /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
201 /// (e.g., `.lines()`). Reads to this handle are otherwise locked with respect
204 /// This handle implements the `Read` trait, but beware that concurrent reads
205 /// of `Stdin` must be executed with care.
207 /// Created by the [`io::stdin`] method.
209 /// [`io::stdin`]: stdin
211 /// ### Note: Windows Portability Consideration
213 /// When operating in a console, the Windows implementation of this stream does not support
214 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
220 /// use std::io::{self, Read};
222 /// fn main() -> io::Result<()> {
223 /// let mut buffer = String::new();
224 /// let mut stdin = io::stdin(); // We get `Stdin` here.
225 /// stdin.read_to_string(&mut buffer)?;
229 #[stable(feature = "rust1", since = "1.0.0")]
231 inner
: &'
static Mutex
<BufReader
<StdinRaw
>>,
234 /// A locked reference to the [`Stdin`] handle.
236 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
237 /// is constructed via the [`Stdin::lock`] method.
239 /// ### Note: Windows Portability Consideration
241 /// When operating in a console, the Windows implementation of this stream does not support
242 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
248 /// use std::io::{self, Read};
250 /// fn main() -> io::Result<()> {
251 /// let mut buffer = String::new();
252 /// let stdin = io::stdin(); // We get `Stdin` here.
254 /// let mut handle = stdin.lock(); // We get `StdinLock` here.
255 /// handle.read_to_string(&mut buffer)?;
256 /// } // `StdinLock` is dropped here.
260 #[stable(feature = "rust1", since = "1.0.0")]
261 pub struct StdinLock
<'a
> {
262 inner
: MutexGuard
<'a
, BufReader
<StdinRaw
>>,
265 /// Constructs a new handle to the standard input of the current process.
267 /// Each handle returned is a reference to a shared global buffer whose access
268 /// is synchronized via a mutex. If you need more explicit control over
269 /// locking, see the [`Stdin::lock`] method.
271 /// ### Note: Windows Portability Consideration
272 /// When operating in a console, the Windows implementation of this stream does not support
273 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
278 /// Using implicit synchronization:
281 /// use std::io::{self, Read};
283 /// fn main() -> io::Result<()> {
284 /// let mut buffer = String::new();
285 /// io::stdin().read_to_string(&mut buffer)?;
290 /// Using explicit synchronization:
293 /// use std::io::{self, Read};
295 /// fn main() -> io::Result<()> {
296 /// let mut buffer = String::new();
297 /// let stdin = io::stdin();
298 /// let mut handle = stdin.lock();
300 /// handle.read_to_string(&mut buffer)?;
304 #[stable(feature = "rust1", since = "1.0.0")]
305 pub fn stdin() -> Stdin
{
306 static INSTANCE
: SyncOnceCell
<Mutex
<BufReader
<StdinRaw
>>> = SyncOnceCell
::new();
308 inner
: INSTANCE
.get_or_init(|| {
309 Mutex
::new(BufReader
::with_capacity(stdio
::STDIN_BUF_SIZE
, stdin_raw()))
315 /// Locks this handle to the standard input stream, returning a readable
318 /// The lock is released when the returned lock goes out of scope. The
319 /// returned guard also implements the [`Read`] and [`BufRead`] traits for
320 /// accessing the underlying data.
325 /// use std::io::{self, Read};
327 /// fn main() -> io::Result<()> {
328 /// let mut buffer = String::new();
329 /// let stdin = io::stdin();
330 /// let mut handle = stdin.lock();
332 /// handle.read_to_string(&mut buffer)?;
336 #[stable(feature = "rust1", since = "1.0.0")]
337 pub fn lock(&self) -> StdinLock
<'_
> {
338 StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
341 /// Locks this handle and reads a line of input, appending it to the specified buffer.
343 /// For detailed semantics of this method, see the documentation on
344 /// [`BufRead::read_line`].
351 /// let mut input = String::new();
352 /// match io::stdin().read_line(&mut input) {
354 /// println!("{} bytes read", n);
355 /// println!("{}", input);
357 /// Err(error) => println!("error: {}", error),
361 /// You can run the example one of two ways:
363 /// - Pipe some text to it, e.g., `printf foo | path/to/executable`
364 /// - Give it text interactively by running the executable directly,
365 /// in which case it will wait for the Enter key to be pressed before
367 #[stable(feature = "rust1", since = "1.0.0")]
368 pub fn read_line(&self, buf
: &mut String
) -> io
::Result
<usize> {
369 self.lock().read_line(buf
)
373 #[stable(feature = "std_debug", since = "1.16.0")]
374 impl fmt
::Debug
for Stdin
{
375 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
376 f
.pad("Stdin { .. }")
380 #[stable(feature = "rust1", since = "1.0.0")]
381 impl Read
for Stdin
{
382 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
383 self.lock().read(buf
)
385 fn read_vectored(&mut self, bufs
: &mut [IoSliceMut
<'_
>]) -> io
::Result
<usize> {
386 self.lock().read_vectored(bufs
)
389 fn is_read_vectored(&self) -> bool
{
390 self.lock().is_read_vectored()
393 unsafe fn initializer(&self) -> Initializer
{
396 fn read_to_end(&mut self, buf
: &mut Vec
<u8>) -> io
::Result
<usize> {
397 self.lock().read_to_end(buf
)
399 fn read_to_string(&mut self, buf
: &mut String
) -> io
::Result
<usize> {
400 self.lock().read_to_string(buf
)
402 fn read_exact(&mut self, buf
: &mut [u8]) -> io
::Result
<()> {
403 self.lock().read_exact(buf
)
407 // only used by platform-dependent io::copy specializations, i.e. unused on some platforms
408 #[cfg(any(target_os = "linux", target_os = "android"))]
410 pub(crate) fn as_mut_buf(&mut self) -> &mut BufReader
<impl Read
> {
415 #[stable(feature = "rust1", since = "1.0.0")]
416 impl Read
for StdinLock
<'_
> {
417 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
421 fn read_vectored(&mut self, bufs
: &mut [IoSliceMut
<'_
>]) -> io
::Result
<usize> {
422 self.inner
.read_vectored(bufs
)
426 fn is_read_vectored(&self) -> bool
{
427 self.inner
.is_read_vectored()
431 unsafe fn initializer(&self) -> Initializer
{
435 fn read_to_end(&mut self, buf
: &mut Vec
<u8>) -> io
::Result
<usize> {
436 self.inner
.read_to_end(buf
)
439 fn read_to_string(&mut self, buf
: &mut String
) -> io
::Result
<usize> {
440 self.inner
.read_to_string(buf
)
443 fn read_exact(&mut self, buf
: &mut [u8]) -> io
::Result
<()> {
444 self.inner
.read_exact(buf
)
448 #[stable(feature = "rust1", since = "1.0.0")]
449 impl BufRead
for StdinLock
<'_
> {
450 fn fill_buf(&mut self) -> io
::Result
<&[u8]> {
451 self.inner
.fill_buf()
454 fn consume(&mut self, n
: usize) {
455 self.inner
.consume(n
)
458 fn read_until(&mut self, byte
: u8, buf
: &mut Vec
<u8>) -> io
::Result
<usize> {
459 self.inner
.read_until(byte
, buf
)
462 fn read_line(&mut self, buf
: &mut String
) -> io
::Result
<usize> {
463 self.inner
.read_line(buf
)
467 #[stable(feature = "std_debug", since = "1.16.0")]
468 impl fmt
::Debug
for StdinLock
<'_
> {
469 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
470 f
.pad("StdinLock { .. }")
474 /// A handle to the global standard output stream of the current process.
476 /// Each handle shares a global buffer of data to be written to the standard
477 /// output stream. Access is also synchronized via a lock and explicit control
478 /// over locking is available via the [`lock`] method.
480 /// Created by the [`io::stdout`] method.
482 /// ### Note: Windows Portability Consideration
483 /// When operating in a console, the Windows implementation of this stream does not support
484 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
487 /// [`lock`]: Stdout::lock
488 /// [`io::stdout`]: stdout
489 #[stable(feature = "rust1", since = "1.0.0")]
491 // FIXME: this should be LineWriter or BufWriter depending on the state of
492 // stdout (tty or not). Note that if this is not line buffered it
493 // should also flush-on-panic or some form of flush-on-abort.
494 inner
: Pin
<&'
static ReentrantMutex
<RefCell
<LineWriter
<StdoutRaw
>>>>,
497 /// A locked reference to the [`Stdout`] handle.
499 /// This handle implements the [`Write`] trait, and is constructed via
500 /// the [`Stdout::lock`] method. See its documentation for more.
502 /// ### Note: Windows Portability Consideration
503 /// When operating in a console, the Windows implementation of this stream does not support
504 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
506 #[stable(feature = "rust1", since = "1.0.0")]
507 pub struct StdoutLock
<'a
> {
508 inner
: ReentrantMutexGuard
<'a
, RefCell
<LineWriter
<StdoutRaw
>>>,
511 /// Constructs a new handle to the standard output of the current process.
513 /// Each handle returned is a reference to a shared global buffer whose access
514 /// is synchronized via a mutex. If you need more explicit control over
515 /// locking, see the [`Stdout::lock`] method.
517 /// ### Note: Windows Portability Consideration
518 /// When operating in a console, the Windows implementation of this stream does not support
519 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
524 /// Using implicit synchronization:
527 /// use std::io::{self, Write};
529 /// fn main() -> io::Result<()> {
530 /// io::stdout().write_all(b"hello world")?;
536 /// Using explicit synchronization:
539 /// use std::io::{self, Write};
541 /// fn main() -> io::Result<()> {
542 /// let stdout = io::stdout();
543 /// let mut handle = stdout.lock();
545 /// handle.write_all(b"hello world")?;
550 #[stable(feature = "rust1", since = "1.0.0")]
551 pub fn stdout() -> Stdout
{
552 static INSTANCE
: SyncOnceCell
<ReentrantMutex
<RefCell
<LineWriter
<StdoutRaw
>>>> =
556 if let Some(instance
) = INSTANCE
.get() {
557 // Flush the data and disable buffering during shutdown
558 // by replacing the line writer by one with zero
559 // buffering capacity.
560 // We use try_lock() instead of lock(), because someone
561 // might have leaked a StdoutLock, which would
562 // otherwise cause a deadlock here.
563 if let Some(lock
) = Pin
::static_ref(instance
).try_lock() {
564 *lock
.borrow_mut() = LineWriter
::with_capacity(0, stdout_raw());
570 inner
: Pin
::static_ref(&INSTANCE
).get_or_init_pin(
572 let _
= sys_common
::at_exit(cleanup
);
573 ReentrantMutex
::new(RefCell
::new(LineWriter
::new(stdout_raw())))
575 |mutex
| unsafe { mutex.init() }
,
581 /// Locks this handle to the standard output stream, returning a writable
584 /// The lock is released when the returned lock goes out of scope. The
585 /// returned guard also implements the `Write` trait for writing data.
590 /// use std::io::{self, Write};
592 /// fn main() -> io::Result<()> {
593 /// let stdout = io::stdout();
594 /// let mut handle = stdout.lock();
596 /// handle.write_all(b"hello world")?;
601 #[stable(feature = "rust1", since = "1.0.0")]
602 pub fn lock(&self) -> StdoutLock
<'_
> {
603 StdoutLock { inner: self.inner.lock() }
607 #[stable(feature = "std_debug", since = "1.16.0")]
608 impl fmt
::Debug
for Stdout
{
609 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
610 f
.pad("Stdout { .. }")
614 #[stable(feature = "rust1", since = "1.0.0")]
615 impl Write
for Stdout
{
616 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
619 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
620 (&*self).write_vectored(bufs
)
623 fn is_write_vectored(&self) -> bool
{
624 io
::Write
::is_write_vectored(&&*self)
626 fn flush(&mut self) -> io
::Result
<()> {
629 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
630 (&*self).write_all(buf
)
632 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
633 (&*self).write_all_vectored(bufs
)
635 fn write_fmt(&mut self, args
: fmt
::Arguments
<'_
>) -> io
::Result
<()> {
636 (&*self).write_fmt(args
)
640 #[stable(feature = "write_mt", since = "1.48.0")]
641 impl Write
for &Stdout
{
642 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
643 self.lock().write(buf
)
645 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
646 self.lock().write_vectored(bufs
)
649 fn is_write_vectored(&self) -> bool
{
650 self.lock().is_write_vectored()
652 fn flush(&mut self) -> io
::Result
<()> {
655 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
656 self.lock().write_all(buf
)
658 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
659 self.lock().write_all_vectored(bufs
)
661 fn write_fmt(&mut self, args
: fmt
::Arguments
<'_
>) -> io
::Result
<()> {
662 self.lock().write_fmt(args
)
666 #[stable(feature = "rust1", since = "1.0.0")]
667 impl Write
for StdoutLock
<'_
> {
668 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
669 self.inner
.borrow_mut().write(buf
)
671 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
672 self.inner
.borrow_mut().write_vectored(bufs
)
675 fn is_write_vectored(&self) -> bool
{
676 self.inner
.borrow_mut().is_write_vectored()
678 fn flush(&mut self) -> io
::Result
<()> {
679 self.inner
.borrow_mut().flush()
681 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
682 self.inner
.borrow_mut().write_all(buf
)
684 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
685 self.inner
.borrow_mut().write_all_vectored(bufs
)
689 #[stable(feature = "std_debug", since = "1.16.0")]
690 impl fmt
::Debug
for StdoutLock
<'_
> {
691 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
692 f
.pad("StdoutLock { .. }")
696 /// A handle to the standard error stream of a process.
698 /// For more information, see the [`io::stderr`] method.
700 /// [`io::stderr`]: stderr
702 /// ### Note: Windows Portability Consideration
703 /// When operating in a console, the Windows implementation of this stream does not support
704 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
706 #[stable(feature = "rust1", since = "1.0.0")]
708 inner
: Pin
<&'
static ReentrantMutex
<RefCell
<StderrRaw
>>>,
711 /// A locked reference to the [`Stderr`] handle.
713 /// This handle implements the [`Write`] trait and is constructed via
714 /// the [`Stderr::lock`] method. See its documentation for more.
716 /// ### Note: Windows Portability Consideration
717 /// When operating in a console, the Windows implementation of this stream does not support
718 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
720 #[stable(feature = "rust1", since = "1.0.0")]
721 pub struct StderrLock
<'a
> {
722 inner
: ReentrantMutexGuard
<'a
, RefCell
<StderrRaw
>>,
725 /// Constructs a new handle to the standard error of the current process.
727 /// This handle is not buffered.
729 /// ### Note: Windows Portability Consideration
730 /// When operating in a console, the Windows implementation of this stream does not support
731 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
736 /// Using implicit synchronization:
739 /// use std::io::{self, Write};
741 /// fn main() -> io::Result<()> {
742 /// io::stderr().write_all(b"hello world")?;
748 /// Using explicit synchronization:
751 /// use std::io::{self, Write};
753 /// fn main() -> io::Result<()> {
754 /// let stderr = io::stderr();
755 /// let mut handle = stderr.lock();
757 /// handle.write_all(b"hello world")?;
762 #[stable(feature = "rust1", since = "1.0.0")]
763 pub fn stderr() -> Stderr
{
764 // Note that unlike `stdout()` we don't use `at_exit` here to register a
765 // destructor. Stderr is not buffered , so there's no need to run a
766 // destructor for flushing the buffer
767 static INSTANCE
: SyncOnceCell
<ReentrantMutex
<RefCell
<StderrRaw
>>> = SyncOnceCell
::new();
770 inner
: Pin
::static_ref(&INSTANCE
).get_or_init_pin(
771 || unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) }
,
772 |mutex
| unsafe { mutex.init() }
,
778 /// Locks this handle to the standard error stream, returning a writable
781 /// The lock is released when the returned lock goes out of scope. The
782 /// returned guard also implements the [`Write`] trait for writing data.
787 /// use std::io::{self, Write};
789 /// fn foo() -> io::Result<()> {
790 /// let stderr = io::stderr();
791 /// let mut handle = stderr.lock();
793 /// handle.write_all(b"hello world")?;
798 #[stable(feature = "rust1", since = "1.0.0")]
799 pub fn lock(&self) -> StderrLock
<'_
> {
800 StderrLock { inner: self.inner.lock() }
804 #[stable(feature = "std_debug", since = "1.16.0")]
805 impl fmt
::Debug
for Stderr
{
806 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
807 f
.pad("Stderr { .. }")
811 #[stable(feature = "rust1", since = "1.0.0")]
812 impl Write
for Stderr
{
813 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
816 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
817 (&*self).write_vectored(bufs
)
820 fn is_write_vectored(&self) -> bool
{
821 io
::Write
::is_write_vectored(&&*self)
823 fn flush(&mut self) -> io
::Result
<()> {
826 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
827 (&*self).write_all(buf
)
829 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
830 (&*self).write_all_vectored(bufs
)
832 fn write_fmt(&mut self, args
: fmt
::Arguments
<'_
>) -> io
::Result
<()> {
833 (&*self).write_fmt(args
)
837 #[stable(feature = "write_mt", since = "1.48.0")]
838 impl Write
for &Stderr
{
839 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
840 self.lock().write(buf
)
842 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
843 self.lock().write_vectored(bufs
)
846 fn is_write_vectored(&self) -> bool
{
847 self.lock().is_write_vectored()
849 fn flush(&mut self) -> io
::Result
<()> {
852 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
853 self.lock().write_all(buf
)
855 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
856 self.lock().write_all_vectored(bufs
)
858 fn write_fmt(&mut self, args
: fmt
::Arguments
<'_
>) -> io
::Result
<()> {
859 self.lock().write_fmt(args
)
863 #[stable(feature = "rust1", since = "1.0.0")]
864 impl Write
for StderrLock
<'_
> {
865 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
866 self.inner
.borrow_mut().write(buf
)
868 fn write_vectored(&mut self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
869 self.inner
.borrow_mut().write_vectored(bufs
)
872 fn is_write_vectored(&self) -> bool
{
873 self.inner
.borrow_mut().is_write_vectored()
875 fn flush(&mut self) -> io
::Result
<()> {
876 self.inner
.borrow_mut().flush()
878 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
879 self.inner
.borrow_mut().write_all(buf
)
881 fn write_all_vectored(&mut self, bufs
: &mut [IoSlice
<'_
>]) -> io
::Result
<()> {
882 self.inner
.borrow_mut().write_all_vectored(bufs
)
886 #[stable(feature = "std_debug", since = "1.16.0")]
887 impl fmt
::Debug
for StderrLock
<'_
> {
888 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
889 f
.pad("StderrLock { .. }")
893 /// Sets the thread-local output capture buffer and returns the old one.
895 feature
= "internal_output_capture",
896 reason
= "this function is meant for use in the test crate \
897 and may disappear in the future",
901 pub fn set_output_capture(sink
: Option
<LocalStream
>) -> Option
<LocalStream
> {
902 if sink
.is_none() && !OUTPUT_CAPTURE_USED
.load(Ordering
::Relaxed
) {
903 // OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false.
906 OUTPUT_CAPTURE_USED
.store(true, Ordering
::Relaxed
);
907 OUTPUT_CAPTURE
.with(move |slot
| slot
.replace(sink
))
910 /// Write `args` to the capture buffer if enabled and possible, or `global_s`
911 /// otherwise. `label` identifies the stream in a panic message.
913 /// This function is used to print error messages, so it takes extra
914 /// care to avoid causing a panic when `local_s` is unusable.
915 /// For instance, if the TLS key for the local stream is
916 /// already destroyed, or if the local stream is locked by another
917 /// thread, it will just fall back to the global stream.
919 /// However, if the actual I/O causes an error, this function does panic.
920 fn print_to
<T
>(args
: fmt
::Arguments
<'_
>, global_s
: fn() -> T
, label
: &str)
924 if OUTPUT_CAPTURE_USED
.load(Ordering
::Relaxed
)
925 && OUTPUT_CAPTURE
.try_with(|s
| {
926 // Note that we completely remove a local sink to write to in case
927 // our printing recursively panics/prints, so the recursive
928 // panic/print goes to the global sink instead of our local sink.
930 let _
= w
.lock().unwrap_or_else(|e
| e
.into_inner()).write_fmt(args
);
935 // Succesfully wrote to capture buffer.
939 if let Err(e
) = global_s().write_fmt(args
) {
940 panic
!("failed printing to {}: {}", label
, e
);
945 feature
= "print_internals",
946 reason
= "implementation detail which may disappear or be replaced at any time",
951 pub fn _print(args
: fmt
::Arguments
<'_
>) {
952 print_to(args
, stdout
, "stdout");
956 feature
= "print_internals",
957 reason
= "implementation detail which may disappear or be replaced at any time",
962 pub fn _eprint(args
: fmt
::Arguments
<'_
>) {
963 print_to(args
, stderr
, "stderr");
967 pub use realstd
::io
::{_eprint, _print}
;