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<()> {