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