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