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