Skip to main content

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