std/io/stdio.rs
1#![cfg_attr(test, allow(unused))]
2
3#[cfg(test)]
4mod tests;
5
6use crate::cell::{Cell, RefCell};
7use crate::fmt;
8use crate::fs::File;
9use crate::io::prelude::*;
10use crate::io::{
11 self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte,
12};
13use crate::panic::{RefUnwindSafe, UnwindSafe};
14use crate::sync::atomic::{AtomicBool, Ordering};
15use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantLock, ReentrantLockGuard};
16use crate::sys::stdio;
17use crate::thread::AccessError;
18
19type LocalStream = Arc<Mutex<Vec<u8>>>;
20
21thread_local! {
22 /// Used by the test crate to capture the output of the print macros and panics.
23 static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = const {
24 Cell::new(None)
25 }
26}
27
28/// Flag to indicate OUTPUT_CAPTURE is used.
29///
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.
33///
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.
40static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false);
41
42/// A handle to a raw instance of the standard input stream of this process.
43///
44/// This handle is not synchronized or buffered in any fashion. Constructed via
45/// the `std::io::stdio::stdin_raw` function.
46struct StdinRaw(stdio::Stdin);
47
48/// A handle to a raw instance of the standard output stream of this process.
49///
50/// This handle is not synchronized or buffered in any fashion. Constructed via
51/// the `std::io::stdio::stdout_raw` function.
52struct StdoutRaw(stdio::Stdout);
53
54/// A handle to a raw instance of the standard output stream of this process.
55///
56/// This handle is not synchronized or buffered in any fashion. Constructed via
57/// the `std::io::stdio::stderr_raw` function.
58struct StderrRaw(stdio::Stderr);
59
60/// Constructs a new raw handle to the standard input of this process.
61///
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.
65///
66/// The returned handle has no external synchronization or buffering.
67#[unstable(feature = "libstd_sys_internals", issue = "none")]
68const fn stdin_raw() -> StdinRaw {
69 StdinRaw(stdio::Stdin::new())
70}
71
72/// Constructs a new raw handle to the standard output stream of this process.
73///
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.
78///
79/// The returned handle has no external synchronization or buffering layered on
80/// top.
81#[unstable(feature = "libstd_sys_internals", issue = "none")]
82const fn stdout_raw() -> StdoutRaw {
83 StdoutRaw(stdio::Stdout::new())
84}
85
86/// Constructs a new raw handle to the standard error stream of this process.
87///
88/// The returned handle does not interact with any other handles created nor
89/// handles returned by `std::io::stderr`.
90///
91/// The returned handle has no external synchronization or buffering layered on
92/// top.
93#[unstable(feature = "libstd_sys_internals", issue = "none")]
94const fn stderr_raw() -> StderrRaw {
95 StderrRaw(stdio::Stderr::new())
96}
97
98impl Read for StdinRaw {
99 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
100 handle_ebadf(self.0.read(buf), 0)
101 }
102
103 fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
104 handle_ebadf(self.0.read_buf(buf), ())
105 }
106
107 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
108 handle_ebadf(self.0.read_vectored(bufs), 0)
109 }
110
111 #[inline]
112 fn is_read_vectored(&self) -> bool {
113 self.0.is_read_vectored()
114 }
115
116 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
117 handle_ebadf(self.0.read_to_end(buf), 0)
118 }
119
120 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
121 handle_ebadf(self.0.read_to_string(buf), 0)
122 }
123}
124
125impl Write for StdoutRaw {
126 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
127 handle_ebadf(self.0.write(buf), buf.len())
128 }
129
130 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
131 let total = || bufs.iter().map(|b| b.len()).sum();
132 handle_ebadf_lazy(self.0.write_vectored(bufs), total)
133 }
134
135 #[inline]
136 fn is_write_vectored(&self) -> bool {
137 self.0.is_write_vectored()
138 }
139
140 fn flush(&mut self) -> io::Result<()> {
141 handle_ebadf(self.0.flush(), ())
142 }
143
144 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
145 handle_ebadf(self.0.write_all(buf), ())
146 }
147
148 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
149 handle_ebadf(self.0.write_all_vectored(bufs), ())
150 }
151
152 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
153 handle_ebadf(self.0.write_fmt(fmt), ())
154 }
155}
156
157impl Write for StderrRaw {
158 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
159 handle_ebadf(self.0.write(buf), buf.len())
160 }
161
162 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
163 let total = || bufs.iter().map(|b| b.len()).sum();
164 handle_ebadf_lazy(self.0.write_vectored(bufs), total)
165 }
166
167 #[inline]
168 fn is_write_vectored(&self) -> bool {
169 self.0.is_write_vectored()
170 }
171
172 fn flush(&mut self) -> io::Result<()> {
173 handle_ebadf(self.0.flush(), ())
174 }
175
176 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
177 handle_ebadf(self.0.write_all(buf), ())
178 }
179
180 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
181 handle_ebadf(self.0.write_all_vectored(bufs), ())
182 }
183
184 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
185 handle_ebadf(self.0.write_fmt(fmt), ())
186 }
187}
188
189fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
190 match r {
191 Err(ref e) if stdio::is_ebadf(e) => Ok(default),
192 r => r,
193 }
194}
195
196fn handle_ebadf_lazy<T>(r: io::Result<T>, default: impl FnOnce() -> T) -> io::Result<T> {
197 match r {
198 Err(ref e) if stdio::is_ebadf(e) => Ok(default()),
199 r => r,
200 }
201}
202
203/// A handle to the standard input stream of a process.
204///
205/// Each handle is a shared reference to a global buffer of input data to this
206/// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
207/// (e.g., `.lines()`). Reads to this handle are otherwise locked with respect
208/// to other reads.
209///
210/// This handle implements the `Read` trait, but beware that concurrent reads
211/// of `Stdin` must be executed with care.
212///
213/// Created by the [`io::stdin`] method.
214///
215/// [`io::stdin`]: stdin
216///
217/// ### Note: Windows Portability Considerations
218///
219/// When operating in a console, the Windows implementation of this stream does not support
220/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
221/// an error.
222///
223/// In a process with a detached console, such as one using
224/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
225/// the contained handle will be null. In such cases, the standard library's `Read` and
226/// `Write` will do nothing and silently succeed. All other I/O operations, via the
227/// standard library or via raw Windows API calls, will fail.
228///
229/// # Examples
230///
231/// ```no_run
232/// use std::io;
233///
234/// fn main() -> io::Result<()> {
235/// let mut buffer = String::new();
236/// let stdin = io::stdin(); // We get `Stdin` here.
237/// stdin.read_line(&mut buffer)?;
238/// Ok(())
239/// }
240/// ```
241#[stable(feature = "rust1", since = "1.0.0")]
242#[cfg_attr(not(test), rustc_diagnostic_item = "Stdin")]
243pub struct Stdin {
244 inner: &'static Mutex<BufReader<StdinRaw>>,
245}
246
247/// A locked reference to the [`Stdin`] handle.
248///
249/// This handle implements both the [`Read`] and [`BufRead`] traits, and
250/// is constructed via the [`Stdin::lock`] method.
251///
252/// ### Note: Windows Portability Considerations
253///
254/// When operating in a console, the Windows implementation of this stream does not support
255/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
256/// an error.
257///
258/// In a process with a detached console, such as one using
259/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
260/// the contained handle will be null. In such cases, the standard library's `Read` and
261/// `Write` will do nothing and silently succeed. All other I/O operations, via the
262/// standard library or via raw Windows API calls, will fail.
263///
264/// # Examples
265///
266/// ```no_run
267/// use std::io::{self, BufRead};
268///
269/// fn main() -> io::Result<()> {
270/// let mut buffer = String::new();
271/// let stdin = io::stdin(); // We get `Stdin` here.
272/// {
273/// let mut handle = stdin.lock(); // We get `StdinLock` here.
274/// handle.read_line(&mut buffer)?;
275/// } // `StdinLock` is dropped here.
276/// Ok(())
277/// }
278/// ```
279#[must_use = "if unused stdin will immediately unlock"]
280#[stable(feature = "rust1", since = "1.0.0")]
281pub struct StdinLock<'a> {
282 inner: MutexGuard<'a, BufReader<StdinRaw>>,
283}
284
285/// Constructs a new handle to the standard input of the current process.
286///
287/// Each handle returned is a reference to a shared global buffer whose access
288/// is synchronized via a mutex. If you need more explicit control over
289/// locking, see the [`Stdin::lock`] method.
290///
291/// ### Note: Windows Portability Considerations
292///
293/// When operating in a console, the Windows implementation of this stream does not support
294/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
295/// an error.
296///
297/// In a process with a detached console, such as one using
298/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
299/// the contained handle will be null. In such cases, the standard library's `Read` and
300/// `Write` will do nothing and silently succeed. All other I/O operations, via the
301/// standard library or via raw Windows API calls, will fail.
302///
303/// # Examples
304///
305/// Using implicit synchronization:
306///
307/// ```no_run
308/// use std::io;
309///
310/// fn main() -> io::Result<()> {
311/// let mut buffer = String::new();
312/// io::stdin().read_line(&mut buffer)?;
313/// Ok(())
314/// }
315/// ```
316///
317/// Using explicit synchronization:
318///
319/// ```no_run
320/// use std::io::{self, BufRead};
321///
322/// fn main() -> io::Result<()> {
323/// let mut buffer = String::new();
324/// let stdin = io::stdin();
325/// let mut handle = stdin.lock();
326///
327/// handle.read_line(&mut buffer)?;
328/// Ok(())
329/// }
330/// ```
331#[must_use]
332#[stable(feature = "rust1", since = "1.0.0")]
333pub fn stdin() -> Stdin {
334 static INSTANCE: OnceLock<Mutex<BufReader<StdinRaw>>> = OnceLock::new();
335 Stdin {
336 inner: INSTANCE.get_or_init(|| {
337 Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin_raw()))
338 }),
339 }
340}
341
342impl Stdin {
343 /// Locks this handle to the standard input stream, returning a readable
344 /// guard.
345 ///
346 /// The lock is released when the returned lock goes out of scope. The
347 /// returned guard also implements the [`Read`] and [`BufRead`] traits for
348 /// accessing the underlying data.
349 ///
350 /// # Examples
351 ///
352 /// ```no_run
353 /// use std::io::{self, BufRead};
354 ///
355 /// fn main() -> io::Result<()> {
356 /// let mut buffer = String::new();
357 /// let stdin = io::stdin();
358 /// let mut handle = stdin.lock();
359 ///
360 /// handle.read_line(&mut buffer)?;
361 /// Ok(())
362 /// }
363 /// ```
364 #[stable(feature = "rust1", since = "1.0.0")]
365 pub fn lock(&self) -> StdinLock<'static> {
366 // Locks this handle with 'static lifetime. This depends on the
367 // implementation detail that the underlying `Mutex` is static.
368 StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
369 }
370
371 /// Locks this handle and reads a line of input, appending it to the specified buffer.
372 ///
373 /// For detailed semantics of this method, see the documentation on
374 /// [`BufRead::read_line`]. In particular:
375 /// * Previous content of the buffer will be preserved. To avoid appending
376 /// to the buffer, you need to [`clear`] it first.
377 /// * The trailing newline character, if any, is included in the buffer.
378 ///
379 /// [`clear`]: String::clear
380 ///
381 /// # Examples
382 ///
383 /// ```no_run
384 /// use std::io;
385 ///
386 /// let mut input = String::new();
387 /// match io::stdin().read_line(&mut input) {
388 /// Ok(n) => {
389 /// println!("{n} bytes read");
390 /// println!("{input}");
391 /// }
392 /// Err(error) => println!("error: {error}"),
393 /// }
394 /// ```
395 ///
396 /// You can run the example one of two ways:
397 ///
398 /// - Pipe some text to it, e.g., `printf foo | path/to/executable`
399 /// - Give it text interactively by running the executable directly,
400 /// in which case it will wait for the Enter key to be pressed before
401 /// continuing
402 #[stable(feature = "rust1", since = "1.0.0")]
403 #[rustc_confusables("get_line")]
404 pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
405 self.lock().read_line(buf)
406 }
407
408 /// Consumes this handle and returns an iterator over input lines.
409 ///
410 /// For detailed semantics of this method, see the documentation on
411 /// [`BufRead::lines`].
412 ///
413 /// # Examples
414 ///
415 /// ```no_run
416 /// use std::io;
417 ///
418 /// let lines = io::stdin().lines();
419 /// for line in lines {
420 /// println!("got a line: {}", line.unwrap());
421 /// }
422 /// ```
423 #[must_use = "`self` will be dropped if the result is not used"]
424 #[stable(feature = "stdin_forwarders", since = "1.62.0")]
425 pub fn lines(self) -> Lines<StdinLock<'static>> {
426 self.lock().lines()
427 }
428}
429
430#[stable(feature = "std_debug", since = "1.16.0")]
431impl fmt::Debug for Stdin {
432 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433 f.debug_struct("Stdin").finish_non_exhaustive()
434 }
435}
436
437#[stable(feature = "rust1", since = "1.0.0")]
438impl Read for Stdin {
439 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
440 self.lock().read(buf)
441 }
442 fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
443 self.lock().read_buf(buf)
444 }
445 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
446 self.lock().read_vectored(bufs)
447 }
448 #[inline]
449 fn is_read_vectored(&self) -> bool {
450 self.lock().is_read_vectored()
451 }
452 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
453 self.lock().read_to_end(buf)
454 }
455 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
456 self.lock().read_to_string(buf)
457 }
458 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
459 self.lock().read_exact(buf)
460 }
461 fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
462 self.lock().read_buf_exact(cursor)
463 }
464}
465
466#[stable(feature = "read_shared_stdin", since = "1.78.0")]
467impl Read for &Stdin {
468 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
469 self.lock().read(buf)
470 }
471 fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
472 self.lock().read_buf(buf)
473 }
474 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
475 self.lock().read_vectored(bufs)
476 }
477 #[inline]
478 fn is_read_vectored(&self) -> bool {
479 self.lock().is_read_vectored()
480 }
481 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
482 self.lock().read_to_end(buf)
483 }
484 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
485 self.lock().read_to_string(buf)
486 }
487 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
488 self.lock().read_exact(buf)
489 }
490 fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
491 self.lock().read_buf_exact(cursor)
492 }
493}
494
495// only used by platform-dependent io::copy specializations, i.e. unused on some platforms
496#[cfg(any(target_os = "linux", target_os = "android"))]
497impl StdinLock<'_> {
498 pub(crate) fn as_mut_buf(&mut self) -> &mut BufReader<impl Read> {
499 &mut self.inner
500 }
501}
502
503#[stable(feature = "rust1", since = "1.0.0")]
504impl Read for StdinLock<'_> {
505 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
506 self.inner.read(buf)
507 }
508
509 fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
510 self.inner.read_buf(buf)
511 }
512
513 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
514 self.inner.read_vectored(bufs)
515 }
516
517 #[inline]
518 fn is_read_vectored(&self) -> bool {
519 self.inner.is_read_vectored()
520 }
521
522 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
523 self.inner.read_to_end(buf)
524 }
525
526 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
527 self.inner.read_to_string(buf)
528 }
529
530 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
531 self.inner.read_exact(buf)
532 }
533
534 fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
535 self.inner.read_buf_exact(cursor)
536 }
537}
538
539impl SpecReadByte for StdinLock<'_> {
540 #[inline]
541 fn spec_read_byte(&mut self) -> Option<io::Result<u8>> {
542 BufReader::spec_read_byte(&mut *self.inner)
543 }
544}
545
546#[stable(feature = "rust1", since = "1.0.0")]
547impl BufRead for StdinLock<'_> {
548 fn fill_buf(&mut self) -> io::Result<&[u8]> {
549 self.inner.fill_buf()
550 }
551
552 fn consume(&mut self, n: usize) {
553 self.inner.consume(n)
554 }
555
556 fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
557 self.inner.read_until(byte, buf)
558 }
559
560 fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
561 self.inner.read_line(buf)
562 }
563}
564
565#[stable(feature = "std_debug", since = "1.16.0")]
566impl fmt::Debug for StdinLock<'_> {
567 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568 f.debug_struct("StdinLock").finish_non_exhaustive()
569 }
570}
571
572/// A handle to the global standard output stream of the current process.
573///
574/// Each handle shares a global buffer of data to be written to the standard
575/// output stream. Access is also synchronized via a lock and explicit control
576/// over locking is available via the [`lock`] method.
577///
578/// Created by the [`io::stdout`] method.
579///
580/// ### Note: Windows Portability Considerations
581///
582/// When operating in a console, the Windows implementation of this stream does not support
583/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
584/// an error.
585///
586/// In a process with a detached console, such as one using
587/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
588/// the contained handle will be null. In such cases, the standard library's `Read` and
589/// `Write` will do nothing and silently succeed. All other I/O operations, via the
590/// standard library or via raw Windows API calls, will fail.
591///
592/// [`lock`]: Stdout::lock
593/// [`io::stdout`]: stdout
594#[stable(feature = "rust1", since = "1.0.0")]
595pub struct Stdout {
596 // FIXME: this should be LineWriter or BufWriter depending on the state of
597 // stdout (tty or not). Note that if this is not line buffered it
598 // should also flush-on-panic or some form of flush-on-abort.
599 inner: &'static ReentrantLock<RefCell<LineWriter<StdoutRaw>>>,
600}
601
602/// A locked reference to the [`Stdout`] handle.
603///
604/// This handle implements the [`Write`] trait, and is constructed via
605/// the [`Stdout::lock`] method. See its documentation for more.
606///
607/// ### Note: Windows Portability Considerations
608///
609/// When operating in a console, the Windows implementation of this stream does not support
610/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
611/// an error.
612///
613/// In a process with a detached console, such as one using
614/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
615/// the contained handle will be null. In such cases, the standard library's `Read` and
616/// `Write` will do nothing and silently succeed. All other I/O operations, via the
617/// standard library or via raw Windows API calls, will fail.
618#[must_use = "if unused stdout will immediately unlock"]
619#[stable(feature = "rust1", since = "1.0.0")]
620pub struct StdoutLock<'a> {
621 inner: ReentrantLockGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
622}
623
624static STDOUT: OnceLock<ReentrantLock<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
625
626/// Constructs a new handle to the standard output of the current process.
627///
628/// Each handle returned is a reference to a shared global buffer whose access
629/// is synchronized via a mutex. If you need more explicit control over
630/// locking, see the [`Stdout::lock`] method.
631///
632/// ### Note: Windows Portability Considerations
633///
634/// When operating in a console, the Windows implementation of this stream does not support
635/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
636/// an error.
637///
638/// In a process with a detached console, such as one using
639/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
640/// the contained handle will be null. In such cases, the standard library's `Read` and
641/// `Write` will do nothing and silently succeed. All other I/O operations, via the
642/// standard library or via raw Windows API calls, will fail.
643///
644/// # Examples
645///
646/// Using implicit synchronization:
647///
648/// ```no_run
649/// use std::io::{self, Write};
650///
651/// fn main() -> io::Result<()> {
652/// io::stdout().write_all(b"hello world")?;
653///
654/// Ok(())
655/// }
656/// ```
657///
658/// Using explicit synchronization:
659///
660/// ```no_run
661/// use std::io::{self, Write};
662///
663/// fn main() -> io::Result<()> {
664/// let stdout = io::stdout();
665/// let mut handle = stdout.lock();
666///
667/// handle.write_all(b"hello world")?;
668///
669/// Ok(())
670/// }
671/// ```
672#[must_use]
673#[stable(feature = "rust1", since = "1.0.0")]
674#[cfg_attr(not(test), rustc_diagnostic_item = "io_stdout")]
675pub fn stdout() -> Stdout {
676 Stdout {
677 inner: STDOUT
678 .get_or_init(|| ReentrantLock::new(RefCell::new(LineWriter::new(stdout_raw())))),
679 }
680}
681
682// Flush the data and disable buffering during shutdown
683// by replacing the line writer by one with zero
684// buffering capacity.
685pub fn cleanup() {
686 let mut initialized = false;
687 let stdout = STDOUT.get_or_init(|| {
688 initialized = true;
689 ReentrantLock::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
690 });
691
692 if !initialized {
693 // The buffer was previously initialized, overwrite it here.
694 // We use try_lock() instead of lock(), because someone
695 // might have leaked a StdoutLock, which would
696 // otherwise cause a deadlock here.
697 if let Some(lock) = stdout.try_lock() {
698 *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
699 }
700 }
701}
702
703impl Stdout {
704 /// Locks this handle to the standard output stream, returning a writable
705 /// guard.
706 ///
707 /// The lock is released when the returned lock goes out of scope. The
708 /// returned guard also implements the `Write` trait for writing data.
709 ///
710 /// # Examples
711 ///
712 /// ```no_run
713 /// use std::io::{self, Write};
714 ///
715 /// fn main() -> io::Result<()> {
716 /// let mut stdout = io::stdout().lock();
717 ///
718 /// stdout.write_all(b"hello world")?;
719 ///
720 /// Ok(())
721 /// }
722 /// ```
723 #[stable(feature = "rust1", since = "1.0.0")]
724 pub fn lock(&self) -> StdoutLock<'static> {
725 // Locks this handle with 'static lifetime. This depends on the
726 // implementation detail that the underlying `ReentrantMutex` is
727 // static.
728 StdoutLock { inner: self.inner.lock() }
729 }
730}
731
732#[stable(feature = "catch_unwind", since = "1.9.0")]
733impl UnwindSafe for Stdout {}
734
735#[stable(feature = "catch_unwind", since = "1.9.0")]
736impl RefUnwindSafe for Stdout {}
737
738#[stable(feature = "std_debug", since = "1.16.0")]
739impl fmt::Debug for Stdout {
740 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
741 f.debug_struct("Stdout").finish_non_exhaustive()
742 }
743}
744
745#[stable(feature = "rust1", since = "1.0.0")]
746impl Write for Stdout {
747 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
748 (&*self).write(buf)
749 }
750 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
751 (&*self).write_vectored(bufs)
752 }
753 #[inline]
754 fn is_write_vectored(&self) -> bool {
755 io::Write::is_write_vectored(&&*self)
756 }
757 fn flush(&mut self) -> io::Result<()> {
758 (&*self).flush()
759 }
760 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
761 (&*self).write_all(buf)
762 }
763 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
764 (&*self).write_all_vectored(bufs)
765 }
766 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
767 (&*self).write_fmt(args)
768 }
769}
770
771#[stable(feature = "write_mt", since = "1.48.0")]
772impl Write for &Stdout {
773 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
774 self.lock().write(buf)
775 }
776 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
777 self.lock().write_vectored(bufs)
778 }
779 #[inline]
780 fn is_write_vectored(&self) -> bool {
781 self.lock().is_write_vectored()
782 }
783 fn flush(&mut self) -> io::Result<()> {
784 self.lock().flush()
785 }
786 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
787 self.lock().write_all(buf)
788 }
789 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
790 self.lock().write_all_vectored(bufs)
791 }
792 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
793 self.lock().write_fmt(args)
794 }
795}
796
797#[stable(feature = "catch_unwind", since = "1.9.0")]
798impl UnwindSafe for StdoutLock<'_> {}
799
800#[stable(feature = "catch_unwind", since = "1.9.0")]
801impl RefUnwindSafe for StdoutLock<'_> {}
802
803#[stable(feature = "rust1", since = "1.0.0")]
804impl Write for StdoutLock<'_> {
805 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
806 self.inner.borrow_mut().write(buf)
807 }
808 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
809 self.inner.borrow_mut().write_vectored(bufs)
810 }
811 #[inline]
812 fn is_write_vectored(&self) -> bool {
813 self.inner.borrow_mut().is_write_vectored()
814 }
815 fn flush(&mut self) -> io::Result<()> {
816 self.inner.borrow_mut().flush()
817 }
818 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
819 self.inner.borrow_mut().write_all(buf)
820 }
821 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
822 self.inner.borrow_mut().write_all_vectored(bufs)
823 }
824}
825
826#[stable(feature = "std_debug", since = "1.16.0")]
827impl fmt::Debug for StdoutLock<'_> {
828 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
829 f.debug_struct("StdoutLock").finish_non_exhaustive()
830 }
831}
832
833/// A handle to the standard error stream of a process.
834///
835/// For more information, see the [`io::stderr`] method.
836///
837/// [`io::stderr`]: stderr
838///
839/// ### Note: Windows Portability Considerations
840///
841/// When operating in a console, the Windows implementation of this stream does not support
842/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
843/// an error.
844///
845/// In a process with a detached console, such as one using
846/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
847/// the contained handle will be null. In such cases, the standard library's `Read` and
848/// `Write` will do nothing and silently succeed. All other I/O operations, via the
849/// standard library or via raw Windows API calls, will fail.
850#[stable(feature = "rust1", since = "1.0.0")]
851pub struct Stderr {
852 inner: &'static ReentrantLock<RefCell<StderrRaw>>,
853}
854
855/// A locked reference to the [`Stderr`] handle.
856///
857/// This handle implements the [`Write`] trait and is constructed via
858/// the [`Stderr::lock`] method. See its documentation for more.
859///
860/// ### Note: Windows Portability Considerations
861///
862/// When operating in a console, the Windows implementation of this stream does not support
863/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
864/// an error.
865///
866/// In a process with a detached console, such as one using
867/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
868/// the contained handle will be null. In such cases, the standard library's `Read` and
869/// `Write` will do nothing and silently succeed. All other I/O operations, via the
870/// standard library or via raw Windows API calls, will fail.
871#[must_use = "if unused stderr will immediately unlock"]
872#[stable(feature = "rust1", since = "1.0.0")]
873pub struct StderrLock<'a> {
874 inner: ReentrantLockGuard<'a, RefCell<StderrRaw>>,
875}
876
877/// Constructs a new handle to the standard error of the current process.
878///
879/// This handle is not buffered.
880///
881/// ### Note: Windows Portability Considerations
882///
883/// When operating in a console, the Windows implementation of this stream does not support
884/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
885/// an error.
886///
887/// In a process with a detached console, such as one using
888/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
889/// the contained handle will be null. In such cases, the standard library's `Read` and
890/// `Write` will do nothing and silently succeed. All other I/O operations, via the
891/// standard library or via raw Windows API calls, will fail.
892///
893/// # Examples
894///
895/// Using implicit synchronization:
896///
897/// ```no_run
898/// use std::io::{self, Write};
899///
900/// fn main() -> io::Result<()> {
901/// io::stderr().write_all(b"hello world")?;
902///
903/// Ok(())
904/// }
905/// ```
906///
907/// Using explicit synchronization:
908///
909/// ```no_run
910/// use std::io::{self, Write};
911///
912/// fn main() -> io::Result<()> {
913/// let stderr = io::stderr();
914/// let mut handle = stderr.lock();
915///
916/// handle.write_all(b"hello world")?;
917///
918/// Ok(())
919/// }
920/// ```
921#[must_use]
922#[stable(feature = "rust1", since = "1.0.0")]
923#[cfg_attr(not(test), rustc_diagnostic_item = "io_stderr")]
924pub fn stderr() -> Stderr {
925 // Note that unlike `stdout()` we don't use `at_exit` here to register a
926 // destructor. Stderr is not buffered, so there's no need to run a
927 // destructor for flushing the buffer
928 static INSTANCE: ReentrantLock<RefCell<StderrRaw>> =
929 ReentrantLock::new(RefCell::new(stderr_raw()));
930
931 Stderr { inner: &INSTANCE }
932}
933
934impl Stderr {
935 /// Locks this handle to the standard error stream, returning a writable
936 /// guard.
937 ///
938 /// The lock is released when the returned lock goes out of scope. The
939 /// returned guard also implements the [`Write`] trait for writing data.
940 ///
941 /// # Examples
942 ///
943 /// ```
944 /// use std::io::{self, Write};
945 ///
946 /// fn foo() -> io::Result<()> {
947 /// let stderr = io::stderr();
948 /// let mut handle = stderr.lock();
949 ///
950 /// handle.write_all(b"hello world")?;
951 ///
952 /// Ok(())
953 /// }
954 /// ```
955 #[stable(feature = "rust1", since = "1.0.0")]
956 pub fn lock(&self) -> StderrLock<'static> {
957 // Locks this handle with 'static lifetime. This depends on the
958 // implementation detail that the underlying `ReentrantMutex` is
959 // static.
960 StderrLock { inner: self.inner.lock() }
961 }
962}
963
964#[stable(feature = "catch_unwind", since = "1.9.0")]
965impl UnwindSafe for Stderr {}
966
967#[stable(feature = "catch_unwind", since = "1.9.0")]
968impl RefUnwindSafe for Stderr {}
969
970#[stable(feature = "std_debug", since = "1.16.0")]
971impl fmt::Debug for Stderr {
972 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
973 f.debug_struct("Stderr").finish_non_exhaustive()
974 }
975}
976
977#[stable(feature = "rust1", since = "1.0.0")]
978impl Write for Stderr {
979 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
980 (&*self).write(buf)
981 }
982 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
983 (&*self).write_vectored(bufs)
984 }
985 #[inline]
986 fn is_write_vectored(&self) -> bool {
987 io::Write::is_write_vectored(&&*self)
988 }
989 fn flush(&mut self) -> io::Result<()> {
990 (&*self).flush()
991 }
992 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
993 (&*self).write_all(buf)
994 }
995 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
996 (&*self).write_all_vectored(bufs)
997 }
998 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
999 (&*self).write_fmt(args)
1000 }
1001}
1002
1003#[stable(feature = "write_mt", since = "1.48.0")]
1004impl Write for &Stderr {
1005 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1006 self.lock().write(buf)
1007 }
1008 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
1009 self.lock().write_vectored(bufs)
1010 }
1011 #[inline]
1012 fn is_write_vectored(&self) -> bool {
1013 self.lock().is_write_vectored()
1014 }
1015 fn flush(&mut self) -> io::Result<()> {
1016 self.lock().flush()
1017 }
1018 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
1019 self.lock().write_all(buf)
1020 }
1021 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
1022 self.lock().write_all_vectored(bufs)
1023 }
1024 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
1025 self.lock().write_fmt(args)
1026 }
1027}
1028
1029#[stable(feature = "catch_unwind", since = "1.9.0")]
1030impl UnwindSafe for StderrLock<'_> {}
1031
1032#[stable(feature = "catch_unwind", since = "1.9.0")]
1033impl RefUnwindSafe for StderrLock<'_> {}
1034
1035#[stable(feature = "rust1", since = "1.0.0")]
1036impl Write for StderrLock<'_> {
1037 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1038 self.inner.borrow_mut().write(buf)
1039 }
1040 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
1041 self.inner.borrow_mut().write_vectored(bufs)
1042 }
1043 #[inline]
1044 fn is_write_vectored(&self) -> bool {
1045 self.inner.borrow_mut().is_write_vectored()
1046 }
1047 fn flush(&mut self) -> io::Result<()> {
1048 self.inner.borrow_mut().flush()
1049 }
1050 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
1051 self.inner.borrow_mut().write_all(buf)
1052 }
1053 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
1054 self.inner.borrow_mut().write_all_vectored(bufs)
1055 }
1056}
1057
1058#[stable(feature = "std_debug", since = "1.16.0")]
1059impl fmt::Debug for StderrLock<'_> {
1060 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1061 f.debug_struct("StderrLock").finish_non_exhaustive()
1062 }
1063}
1064
1065/// Sets the thread-local output capture buffer and returns the old one.
1066#[unstable(
1067 feature = "internal_output_capture",
1068 reason = "this function is meant for use in the test crate \
1069 and may disappear in the future",
1070 issue = "none"
1071)]
1072#[doc(hidden)]
1073pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> {
1074 try_set_output_capture(sink).expect(
1075 "cannot access a Thread Local Storage value \
1076 during or after destruction",
1077 )
1078}
1079
1080/// Tries to set the thread-local output capture buffer and returns the old one.
1081/// This may fail once thread-local destructors are called. It's used in panic
1082/// handling instead of `set_output_capture`.
1083#[unstable(
1084 feature = "internal_output_capture",
1085 reason = "this function is meant for use in the test crate \
1086 and may disappear in the future",
1087 issue = "none"
1088)]
1089#[doc(hidden)]
1090pub fn try_set_output_capture(
1091 sink: Option<LocalStream>,
1092) -> Result<Option<LocalStream>, AccessError> {
1093 if sink.is_none() && !OUTPUT_CAPTURE_USED.load(Ordering::Relaxed) {
1094 // OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false.
1095 return Ok(None);
1096 }
1097 OUTPUT_CAPTURE_USED.store(true, Ordering::Relaxed);
1098 OUTPUT_CAPTURE.try_with(move |slot| slot.replace(sink))
1099}
1100
1101/// Writes `args` to the capture buffer if enabled and possible, or `global_s`
1102/// otherwise. `label` identifies the stream in a panic message.
1103///
1104/// This function is used to print error messages, so it takes extra
1105/// care to avoid causing a panic when `OUTPUT_CAPTURE` is unusable.
1106/// For instance, if the TLS key for output capturing is already destroyed, or
1107/// if the local stream is in use by another thread, it will just fall back to
1108/// the global stream.
1109///
1110/// However, if the actual I/O causes an error, this function does panic.
1111///
1112/// Writing to non-blocking stdout/stderr can cause an error, which will lead
1113/// this function to panic.
1114fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
1115where
1116 T: Write,
1117{
1118 if print_to_buffer_if_capture_used(args) {
1119 // Successfully wrote to capture buffer.
1120 return;
1121 }
1122
1123 if let Err(e) = global_s().write_fmt(args) {
1124 panic!("failed printing to {label}: {e}");
1125 }
1126}
1127
1128fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool {
1129 OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
1130 && OUTPUT_CAPTURE.try_with(|s| {
1131 // Note that we completely remove a local sink to write to in case
1132 // our printing recursively panics/prints, so the recursive
1133 // panic/print goes to the global sink instead of our local sink.
1134 s.take().map(|w| {
1135 let _ = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
1136 s.set(Some(w));
1137 })
1138 }) == Ok(Some(()))
1139}
1140
1141/// Used by impl Termination for Result to print error after `main` or a test
1142/// has returned. Should avoid panicking, although we can't help it if one of
1143/// the Display impls inside args decides to.
1144pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
1145 if print_to_buffer_if_capture_used(args) {
1146 return;
1147 }
1148
1149 // Ignore error if the write fails, for example because stderr is already
1150 // closed. There is not much point panicking at this point.
1151 let _ = stderr().write_fmt(args);
1152}
1153
1154/// Trait to determine if a descriptor/handle refers to a terminal/tty.
1155#[stable(feature = "is_terminal", since = "1.70.0")]
1156pub trait IsTerminal: crate::sealed::Sealed {
1157 /// Returns `true` if the descriptor/handle refers to a terminal/tty.
1158 ///
1159 /// On platforms where Rust does not know how to detect a terminal yet, this will return
1160 /// `false`. This will also return `false` if an unexpected error occurred, such as from
1161 /// passing an invalid file descriptor.
1162 ///
1163 /// # Platform-specific behavior
1164 ///
1165 /// On Windows, in addition to detecting consoles, this currently uses some heuristics to
1166 /// detect older msys/cygwin/mingw pseudo-terminals based on device name: devices with names
1167 /// starting with `msys-` or `cygwin-` and ending in `-pty` will be considered terminals.
1168 /// Note that this [may change in the future][changes].
1169 ///
1170 /// # Examples
1171 ///
1172 /// An example of a type for which `IsTerminal` is implemented is [`Stdin`]:
1173 ///
1174 /// ```no_run
1175 /// use std::io::{self, IsTerminal, Write};
1176 ///
1177 /// fn main() -> io::Result<()> {
1178 /// let stdin = io::stdin();
1179 ///
1180 /// // Indicate that the user is prompted for input, if this is a terminal.
1181 /// if stdin.is_terminal() {
1182 /// print!("> ");
1183 /// io::stdout().flush()?;
1184 /// }
1185 ///
1186 /// let mut name = String::new();
1187 /// let _ = stdin.read_line(&mut name)?;
1188 ///
1189 /// println!("Hello {}", name.trim_end());
1190 ///
1191 /// Ok(())
1192 /// }
1193 /// ```
1194 ///
1195 /// The example can be run in two ways:
1196 ///
1197 /// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable`
1198 /// it will print: `Hello foo`.
1199 /// - If you instead run the example interactively by running `path/to/executable` directly, it will
1200 /// prompt for input.
1201 ///
1202 /// [changes]: io#platform-specific-behavior
1203 /// [`Stdin`]: crate::io::Stdin
1204 #[doc(alias = "isatty")]
1205 #[stable(feature = "is_terminal", since = "1.70.0")]
1206 fn is_terminal(&self) -> bool;
1207}
1208
1209macro_rules! impl_is_terminal {
1210 ($($t:ty),*$(,)?) => {$(
1211 #[unstable(feature = "sealed", issue = "none")]
1212 impl crate::sealed::Sealed for $t {}
1213
1214 #[stable(feature = "is_terminal", since = "1.70.0")]
1215 impl IsTerminal for $t {
1216 #[inline]
1217 fn is_terminal(&self) -> bool {
1218 crate::sys::io::is_terminal(self)
1219 }
1220 }
1221 )*}
1222}
1223
1224impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, StderrLock<'_>);
1225
1226#[unstable(
1227 feature = "print_internals",
1228 reason = "implementation detail which may disappear or be replaced at any time",
1229 issue = "none"
1230)]
1231#[doc(hidden)]
1232#[cfg(not(test))]
1233pub fn _print(args: fmt::Arguments<'_>) {
1234 print_to(args, stdout, "stdout");
1235}
1236
1237#[unstable(
1238 feature = "print_internals",
1239 reason = "implementation detail which may disappear or be replaced at any time",
1240 issue = "none"
1241)]
1242#[doc(hidden)]
1243#[cfg(not(test))]
1244pub fn _eprint(args: fmt::Arguments<'_>) {
1245 print_to(args, stderr, "stderr");
1246}
1247
1248#[cfg(test)]
1249pub use realstd::io::{_eprint, _print};