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