1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
#![cfg_attr(test, allow(unused))]
#[cfg(test)]
mod tests;
use crate::io::prelude::*;
use crate::cell::{Cell, RefCell};
use crate::fmt;
use crate::fs::File;
use crate::io::{self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard};
use crate::sys::stdio;
type LocalStream = Arc<Mutex<Vec<u8>>>;
thread_local! {
/// 测试 crate 用于捕获打印宏和 panics 的输出。
static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = {
Cell::new(None)
}
}
/// 指示使用 OUTPUT_CAPTURE 的标志。
///
/// 如果它为 None 并且从未在任何线程上设置,则此标志设置为 false,并且可以安全地在所有线程上忽略 OUTPUT_CAPTURE,从而节省了时间和内存,以在本地注册未使用的线程。
///
/// 有关内存排序的注意事项:它包含有关是否可能正在使用线程局部变量的信息。
/// 尽管这是一个 γ 标志,但线程之间的内存顺序无关紧要:我们只希望此标志在 set_output_capture 和 print_to *within the 相同线程* 之间具有一致的顺序。
///
/// 在同一线程中,事物始终具有完全一致的顺序。
/// 所以 Ordering::Relaxed 很好。
///
///
///
static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false);
/// 此进程的标准输入流的原始实例的句柄。
///
/// 此句柄不以任何方式同步或缓冲。
/// 通过 `std::io::stdio::stdin_raw` 函数构造。
struct StdinRaw(stdio::Stdin);
/// 此进程的标准输出流的原始实例的句柄。
///
/// 此句柄不以任何方式同步或缓冲。
/// 通过 `std::io::stdio::stdout_raw` 函数构造。
struct StdoutRaw(stdio::Stdout);
/// 此进程的标准输出流的原始实例的句柄。
///
/// 此句柄不以任何方式同步或缓冲。
/// 通过 `std::io::stdio::stderr_raw` 函数构造。
struct StderrRaw(stdio::Stderr);
/// 为这个进程的标准输入创建一个新的原始句柄。
///
/// 返回的句柄不与任何其他创建的句柄交互,也不与 `std::io::stdin` 返回的句柄交互。
/// `std::io::stdin` 句柄缓冲的数据对于从此函数返回的原始句柄不可用。
///
/// 返回的句柄没有外部同步或缓冲。
///
#[unstable(feature = "libstd_sys_internals", issue = "none")]
const fn stdin_raw() -> StdinRaw {
StdinRaw(stdio::Stdin::new())
}
/// 为该进程的标准输出流创建一个新的原始句柄。
///
/// 返回的句柄不与任何其他创建的句柄交互,也不与 `std::io::stdout` 返回的句柄交互。
/// 请注意,数据由 `std::io::stdout` 句柄缓冲,因此通过此原始句柄发生的写操作可能会在之前的写操作之前出现。
///
///
/// 返回的句柄顶部没有分层的外部同步或缓冲。
///
///
#[unstable(feature = "libstd_sys_internals", issue = "none")]
const fn stdout_raw() -> StdoutRaw {
StdoutRaw(stdio::Stdout::new())
}
/// 为该进程的标准错误流创建一个新的原始句柄。
///
/// 返回的句柄不与任何其他创建的句柄交互,也不与 `std::io::stderr` 返回的句柄交互。
///
///
/// 返回的句柄顶部没有分层的外部同步或缓冲。
///
#[unstable(feature = "libstd_sys_internals", issue = "none")]
const fn stderr_raw() -> StderrRaw {
StderrRaw(stdio::Stderr::new())
}
impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
handle_ebadf(self.0.read(buf), 0)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
handle_ebadf(self.0.read_buf(buf), ())
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
handle_ebadf(self.0.read_vectored(bufs), 0)
}
#[inline]
fn is_read_vectored(&self) -> bool {
self.0.is_read_vectored()
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
handle_ebadf(self.0.read_to_end(buf), 0)
}
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
handle_ebadf(self.0.read_to_string(buf), 0)
}
}
impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
handle_ebadf(self.0.write(buf), buf.len())
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let total = bufs.iter().map(|b| b.len()).sum();
handle_ebadf(self.0.write_vectored(bufs), total)
}
#[inline]
fn is_write_vectored(&self) -> bool {
self.0.is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
handle_ebadf(self.0.flush(), ())
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
handle_ebadf(self.0.write_all(buf), ())
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
handle_ebadf(self.0.write_all_vectored(bufs), ())
}
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
handle_ebadf(self.0.write_fmt(fmt), ())
}
}
impl Write for StderrRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
handle_ebadf(self.0.write(buf), buf.len())
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let total = bufs.iter().map(|b| b.len()).sum();
handle_ebadf(self.0.write_vectored(bufs), total)
}
#[inline]
fn is_write_vectored(&self) -> bool {
self.0.is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
handle_ebadf(self.0.flush(), ())
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
handle_ebadf(self.0.write_all(buf), ())
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
handle_ebadf(self.0.write_all_vectored(bufs), ())
}
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
handle_ebadf(self.0.write_fmt(fmt), ())
}
}
fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
match r {
Err(ref e) if stdio::is_ebadf(e) => Ok(default),
r => r,
}
}
/// 进程的标准输入流的句柄。
///
/// 每个句柄都是对该进程输入数据的全局缓冲区的共享引用。可以对句柄进行 `lock`,以获取对 [`BufRead`] 方法 (例如 `.lines()`) 的完全访问权限。
/// 否则,将针对其他读取锁定对此句柄的读取。
///
/// 该句柄实现了 `Read` trait,但请注意,必须谨慎执行 `Stdin` 的并发读取。
///
/// 由 [`io::stdin`] 方法创建。
///
/// [`io::stdin`]: stdin
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试读取无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
/// # Examples
///
/// ```no_run
/// use std::io;
///
/// fn main() -> io::Result<()> {
/// let mut buffer = String::new();
/// let stdin = io::stdin(); // 我们在这里得到 `Stdin`。
/// stdin.read_line(&mut buffer)?;
/// Ok(())
/// }
/// ```
///
///
///
///
///
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdin {
inner: &'static Mutex<BufReader<StdinRaw>>,
}
/// [`Stdin`] 句柄的锁定引用。
///
/// 该句柄同时实现 [`Read`] 和 [`BufRead`] traits,并通过 [`Stdin::lock`] 方法构造。
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试读取无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
/// # Examples
///
/// ```no_run
/// use std::io::{self, BufRead};
///
/// fn main() -> io::Result<()> {
/// let mut buffer = String::new();
/// let stdin = io::stdin(); // 我们在这里得到 `Stdin`。
/// {
/// let mut handle = stdin.lock(); // 我们在这里得到 `StdinLock`。
/// handle.read_line(&mut buffer)?;
/// } // `StdinLock` 被丢弃在这里。
/// Ok(())
/// }
/// ```
///
///
///
#[must_use = "if unused stdin will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdinLock<'a> {
inner: MutexGuard<'a, BufReader<StdinRaw>>,
}
/// 为当前进程的标准输入创建一个新的句柄。
///
/// 返回的每个句柄都是对共享缓冲区的引用,该缓冲区的访问通过互斥锁进行同步。
/// 如果需要对锁定进行更明确的控制,请参见 [`Stdin::lock`] 方法。
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试读取无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
/// # Examples
///
/// 使用隐式同步:
///
/// ```no_run
/// use std::io;
///
/// fn main() -> io::Result<()> {
/// let mut buffer = String::new();
/// io::stdin().read_line(&mut buffer)?;
/// Ok(())
/// }
/// ```
///
/// 使用显式同步:
///
/// ```no_run
/// use std::io::{self, BufRead};
///
/// fn main() -> io::Result<()> {
/// let mut buffer = String::new();
/// let stdin = io::stdin();
/// let mut handle = stdin.lock();
///
/// handle.read_line(&mut buffer)?;
/// Ok(())
/// }
/// ```
///
///
///
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
static INSTANCE: OnceLock<Mutex<BufReader<StdinRaw>>> = OnceLock::new();
Stdin {
inner: INSTANCE.get_or_init(|| {
Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin_raw()))
}),
}
}
impl Stdin {
/// 将此句柄锁定到标准输入流,返回可读的保护。
///
/// 当返回的锁离开作用域时,将释放该锁。
/// 返回的防护还实现了用于访问底层数据的 [`Read`] 和 [`BufRead`] traits。
///
///
/// # Examples
///
/// ```no_run
/// use std::io::{self, BufRead};
///
/// fn main() -> io::Result<()> {
/// let mut buffer = String::new();
/// let stdin = io::stdin();
/// let mut handle = stdin.lock();
///
/// handle.read_line(&mut buffer)?;
/// Ok(())
/// }
/// ```
///
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdinLock<'static> {
// 用 'static 生命周期锁定这个句柄。
// 这取决于底层 `Mutex` 是静态的实现细节。
StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
}
/// 锁定此句柄并读取输入行,并将其添加到指定的缓冲区。
///
/// 有关此方法的详细语义,请参见 [`BufRead::read_line`] 上的文档。
///
/// # Examples
///
/// ```no_run
/// use std::io;
///
/// let mut input = String::new();
/// match io::stdin().read_line(&mut input) {
/// Ok(n) => {
/// println!("{n} bytes read");
/// println!("{input}");
/// }
/// Err(error) => println!("error: {error}"),
/// }
/// ```
///
/// 您可以通过以下两种方式之一运行示例:
///
/// - 通过管道将一些文本传递给它,例如 `printf foo | path/to/executable`
/// - 通过直接运行可执行文件以交互方式输入文本,在这种情况下,它将等待按下 Enter 键,然后继续
///
///
///
#[stable(feature = "rust1", since = "1.0.0")]
pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
self.lock().read_line(buf)
}
/// 消费这个句柄并在输入行上返回一个迭代器。
///
/// 有关此方法的详细语义,请参见 [`BufRead::lines`] 上的文档。
///
///
/// # Examples
///
/// ```no_run
/// use std::io;
///
/// let lines = io::stdin().lines();
/// for line in lines {
/// println!("got a line: {}", line.unwrap());
/// }
/// ```
#[must_use = "`self` will be dropped if the result is not used"]
#[stable(feature = "stdin_forwarders", since = "1.62.0")]
pub fn lines(self) -> Lines<StdinLock<'static>> {
self.lock().lines()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stdin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Stdin").finish_non_exhaustive()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.lock().read(buf)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
self.lock().read_buf(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.lock().read_vectored(bufs)
}
#[inline]
fn is_read_vectored(&self) -> bool {
self.lock().is_read_vectored()
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.lock().read_to_end(buf)
}
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
self.lock().read_to_string(buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.lock().read_exact(buf)
}
}
// 仅由依赖于平台的 io::copy 专业使用,即在某些平台上未使用
#[cfg(any(target_os = "linux", target_os = "android"))]
impl StdinLock<'_> {
pub(crate) fn as_mut_buf(&mut self) -> &mut BufReader<impl Read> {
&mut self.inner
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Read for StdinLock<'_> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
self.inner.read_buf(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.read_vectored(bufs)
}
#[inline]
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
self.inner.read_to_string(buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.inner.read_exact(buf)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for StdinLock<'_> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
self.inner.fill_buf()
}
fn consume(&mut self, n: usize) {
self.inner.consume(n)
}
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_until(byte, buf)
}
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
self.inner.read_line(buf)
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for StdinLock<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StdinLock").finish_non_exhaustive()
}
}
/// 当前进程的标准输出流的句柄。
///
/// 每个句柄共享一个待写入标准输出流的数据缓冲区。
/// 访问也可以通过锁定来同步,并且可以通过 [`lock`] 方法对锁定进行显式控制。
///
/// 由 [`io::stdout`] 方法创建。
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试写入无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
/// [`lock`]: Stdout::lock
/// [`io::stdout`]: stdout
///
///
///
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdout {
// FIXME: 根据 stdout 的状态 (是否为 tty),它应该是 LineWriter 或 BufWriter。
// 请注意,如果这不是行缓冲的,则还应该在 panic 时进行刷新或在中止时进行某种形式的刷新。
//
inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
}
/// [`Stdout`] 句柄的锁定引用。
///
/// 该句柄实现 [`Write`] trait,并通过 [`Stdout::lock`] 方法构造。有关更多信息,请参见其文档。
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试写入无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
///
///
#[must_use = "if unused stdout will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
}
static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
/// 为当前进程的标准输出创建一个新的句柄。
///
/// 返回的每个句柄都是对共享缓冲区的引用,该缓冲区的访问通过互斥锁进行同步。
/// 如果需要对锁定进行更明确的控制,请参见 [`Stdout::lock`] 方法。
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试写入无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
/// # Examples
///
/// 使用隐式同步:
///
/// ```no_run
/// use std::io::{self, Write};
///
/// fn main() -> io::Result<()> {
/// io::stdout().write_all(b"hello world")?;
///
/// Ok(())
/// }
/// ```
///
/// 使用显式同步:
///
/// ```no_run
/// use std::io::{self, Write};
///
/// fn main() -> io::Result<()> {
/// let stdout = io::stdout();
/// let mut handle = stdout.lock();
///
/// handle.write_all(b"hello world")?;
///
/// Ok(())
/// }
/// ```
///
///
///
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
Stdout {
inner: STDOUT
.get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
}
}
// 通过用零缓冲容量将行 writer 替换为 1,刷新数据并在关闭期间禁用缓冲。
//
//
pub fn cleanup() {
let mut initialized = false;
let stdout = STDOUT.get_or_init(|| {
initialized = true;
ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
});
if !initialized {
// 缓冲区先前已初始化,请在此处覆盖它。
// 我们使用 try_lock() 代替 lock(),因为有人可能泄漏了 StdoutLock,否则将在此处导致死锁。
//
//
if let Some(lock) = stdout.try_lock() {
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
}
}
}
impl Stdout {
/// 将此句柄锁定到标准输出流,返回可写防护。
///
///
/// 当返回的锁离开作用域时,将释放该锁。
/// 返回的防护还实现 `Write` trait 来写入数据。
///
/// # Examples
///
/// ```no_run
/// use std::io::{self, Write};
///
/// fn main() -> io::Result<()> {
/// let mut stdout = io::stdout().lock();
///
/// stdout.write_all(b"hello world")?;
///
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdoutLock<'static> {
// 用 'static 生命周期锁定这个句柄。
// 这取决于底层 `ReentrantMutex` 是静态的实现细节。
//
StdoutLock { inner: self.inner.lock() }
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stdout {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Stdout").finish_non_exhaustive()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(&*self).write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
(&*self).write_vectored(bufs)
}
#[inline]
fn is_write_vectored(&self) -> bool {
io::Write::is_write_vectored(&&*self)
}
fn flush(&mut self) -> io::Result<()> {
(&*self).flush()
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
(&*self).write_all(buf)
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
(&*self).write_all_vectored(bufs)
}
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
(&*self).write_fmt(args)
}
}
#[stable(feature = "write_mt", since = "1.48.0")]
impl Write for &Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.lock().write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.lock().write_vectored(bufs)
}
#[inline]
fn is_write_vectored(&self) -> bool {
self.lock().is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.lock().flush()
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.lock().write_all(buf)
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.lock().write_all_vectored(bufs)
}
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
self.lock().write_fmt(args)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for StdoutLock<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.borrow_mut().write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.borrow_mut().write_vectored(bufs)
}
#[inline]
fn is_write_vectored(&self) -> bool {
self.inner.borrow_mut().is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.inner.borrow_mut().flush()
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.inner.borrow_mut().write_all(buf)
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.inner.borrow_mut().write_all_vectored(bufs)
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for StdoutLock<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StdoutLock").finish_non_exhaustive()
}
}
/// 进程的标准错误流的句柄。
///
/// 有关更多信息,请参见 [`io::stderr`] 方法。
///
/// [`io::stderr`]: stderr
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试写入无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
///
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
}
/// [`Stderr`] 句柄的锁定引用。
///
/// 该句柄实现 [`Write`] trait,并通过 [`Stderr::lock`] 方法构造。有关更多信息,请参见其文档。
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试写入无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
///
///
#[must_use = "if unused stderr will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StderrLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
}
/// 为当前进程的标准错误创建一个新的句柄。
///
/// 此句柄未缓冲。
///
/// ### Note: Windows 可移植性注意事项
///
/// 在控制台中操作时,此流的 Windows 实现不支持非 UTF-8 字节序列。
/// 尝试写入无效的 UTF-8 字节将返回错误。
///
/// 在具有分离控制台的进程中,例如使用 `#![windows_subsystem = "windows"]` 的进程,或在从此类进程派生的子进程中,包含的句柄将为空。
///
/// 在这种情况下,标准库的 `Read` 和 `Write` 将什么都不做,默默地成功。
/// 通过标准库或通过原始 Windows API 调用的所有其他 I/O 操作都将失败。
///
/// # Examples
///
/// 使用隐式同步:
///
/// ```no_run
/// use std::io::{self, Write};
///
/// fn main() -> io::Result<()> {
/// io::stderr().write_all(b"hello world")?;
///
/// Ok(())
/// }
/// ```
///
/// 使用显式同步:
///
/// ```no_run
/// use std::io::{self, Write};
///
/// fn main() -> io::Result<()> {
/// let stderr = io::stderr();
/// let mut handle = stderr.lock();
///
/// handle.write_all(b"hello world")?;
///
/// Ok(())
/// }
/// ```
///
///
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
// 请注意,与 `stdout()` 不同,我们在这里不使用 `at_exit` 注册析构函数。
// 标准错误没有缓冲,所以不需要运行析构函数来刷新缓冲区
//
static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
ReentrantMutex::new(RefCell::new(stderr_raw()));
Stderr { inner: &INSTANCE }
}
impl Stderr {
/// 将此句柄锁定到标准错误流,返回可写防护。
///
///
/// 当返回的锁离开作用域时,将释放该锁。
/// 返回的防护还实现 [`Write`] trait 来写入数据。
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// fn foo() -> io::Result<()> {
/// let stderr = io::stderr();
/// let mut handle = stderr.lock();
///
/// handle.write_all(b"hello world")?;
///
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StderrLock<'static> {
// 用 'static 生命周期锁定这个句柄。
// 这取决于底层 `ReentrantMutex` 是静态的实现细节。
//
StderrLock { inner: self.inner.lock() }
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stderr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Stderr").finish_non_exhaustive()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Stderr {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(&*self).write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
(&*self).write_vectored(bufs)
}
#[inline]
fn is_write_vectored(&self) -> bool {
io::Write::is_write_vectored(&&*self)
}
fn flush(&mut self) -> io::Result<()> {
(&*self).flush()
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
(&*self).write_all(buf)
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
(&*self).write_all_vectored(bufs)
}
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
(&*self).write_fmt(args)
}
}
#[stable(feature = "write_mt", since = "1.48.0")]
impl Write for &Stderr {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.lock().write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.lock().write_vectored(bufs)
}
#[inline]
fn is_write_vectored(&self) -> bool {
self.lock().is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.lock().flush()
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.lock().write_all(buf)
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.lock().write_all_vectored(bufs)
}
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
self.lock().write_fmt(args)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for StderrLock<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.borrow_mut().write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.borrow_mut().write_vectored(bufs)
}
#[inline]
fn is_write_vectored(&self) -> bool {
self.inner.borrow_mut().is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.inner.borrow_mut().flush()
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.inner.borrow_mut().write_all(buf)
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.inner.borrow_mut().write_all_vectored(bufs)
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for StderrLock<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StderrLock").finish_non_exhaustive()
}
}
/// 设置线程本地输出捕获缓冲区并返回旧的缓冲区。
#[unstable(
feature = "internal_output_capture",
reason = "this function is meant for use in the test crate \
and may disappear in the future",
issue = "none"
)]
#[doc(hidden)]
pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> {
if sink.is_none() && !OUTPUT_CAPTURE_USED.load(Ordering::Relaxed) {
// OUTPUT_CAPTURE 绝对为 None,因为 OUTPUT_CAPTURE_USED 为 false。
return None;
}
OUTPUT_CAPTURE_USED.store(true, Ordering::Relaxed);
OUTPUT_CAPTURE.with(move |slot| slot.replace(sink))
}
/// 将 `args` 写入捕获缓冲区 (如果已启用且可能的话),否则将其写入 `global_s`。`label` 在 panic 消息中标识流。
///
/// 该函数用于打印错误消息,因此当 `OUTPUT_CAPTURE` 不可用时要特别注意避免引起 panic。
/// 例如,如果 TLS 的输出捕获键已经是本地 TLS 键,或者如果它被另一个线程使用,则它只会退回到该流连接。
///
///
/// 但是,如果实际的 I/O 导致错误,则此函数执行 panic。
///
/// 写入非阻塞 stdout/stderr 可能会导致错误,这将导致该函数 panic。
///
///
///
///
fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
where
T: Write,
{
if print_to_buffer_if_capture_used(args) {
// 已成功写入捕获缓冲区。
return;
}
if let Err(e) = global_s().write_fmt(args) {
panic!("failed printing to {label}: {e}");
}
}
fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool {
OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
&& OUTPUT_CAPTURE.try_with(|s| {
// 请注意,如果我们以递归方式打印 panics/prints,我们将完全删除要写入的本地 sink,因此,递归 panic/print 会转到 sink,而不是我们的本地 sink。
//
//
s.take().map(|w| {
let _ = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
s.set(Some(w));
})
}) == Ok(Some(()))
}
/// 由 impl Termination for Result 用于在 `main` 或测试返回后打印错误。
/// 应该避免 panic,尽管如果 args 中的 Display impls 之一决定这样做,我们将无能为力。
///
pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
if print_to_buffer_if_capture_used(args) {
return;
}
// 如果写入失败,则忽略错误,例如因为标准错误已经关闭。
// 在这一点上,panic 的话没有太大的意义。
let _ = stderr().write_fmt(args);
}
/// Trait 确定 descriptor/handle 是否指代 terminal/tty。
#[stable(feature = "is_terminal", since = "1.70.0")]
pub trait IsTerminal: crate::sealed::Sealed {
/// 如果 descriptor/handle 引用 terminal/tty,则返回 `true`。
///
/// 在 Rust 还不知道如何检测终端的平台上,这将返回 `false`。如果发生意外错误,例如传递无效的文件描述符,这也将返回 `false`。
///
/// # 特定于平台的行为
///
/// 在 Windows 上,除了检测控制台外,目前还使用一些启发式方法根据设备名称检测较旧的 msys/cygwin/mingw 伪终端: 名称以 `msys-` 或 `cygwin-` 开头并以 `-pty` 结尾的设备将被视为终端。
///
/// 注意这个 [将来可能会发生变化][changes]。
///
/// [changes]: io#platform-specific-behavior
///
///
///
#[stable(feature = "is_terminal", since = "1.70.0")]
fn is_terminal(&self) -> bool;
}
macro_rules! impl_is_terminal {
($($t:ty),*$(,)?) => {$(
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for $t {}
#[stable(feature = "is_terminal", since = "1.70.0")]
impl IsTerminal for $t {
#[inline]
fn is_terminal(&self) -> bool {
crate::sys::io::is_terminal(self)
}
}
)*}
}
impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, StderrLock<'_>);
#[unstable(
feature = "print_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
#[doc(hidden)]
#[cfg(not(test))]
pub fn _print(args: fmt::Arguments<'_>) {
print_to(args, stdout, "stdout");
}
#[unstable(
feature = "print_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
#[doc(hidden)]
#[cfg(not(test))]
pub fn _eprint(args: fmt::Arguments<'_>) {
print_to(args, stderr, "stderr");
}
#[cfg(test)]
pub use realstd::io::{_eprint, _print};