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