1use crate::io::{self, BufReader, prelude::*};
2use crate::sync::{Mutex, MutexGuard};
3
4#[cfg(feature = "alloc")]
5use alloc::{string::String, vec::Vec};
6
7struct StdinRaw;
8struct StdoutRaw;
9
10impl Read for StdinRaw {
11 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
13 let mut read_len = 0;
14 while read_len < buf.len() {
15 let len = arceos_api::stdio::ax_console_read_bytes(buf[read_len..].as_mut())?;
16 if len == 0 {
17 break;
18 }
19 read_len += len;
20 }
21 Ok(read_len)
22 }
23}
24
25impl Write for StdoutRaw {
26 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
27 arceos_api::stdio::ax_console_write_bytes(buf)
28 }
29 fn flush(&mut self) -> io::Result<()> {
30 Ok(())
31 }
32}
33
34pub struct Stdin {
36 inner: &'static Mutex<BufReader<StdinRaw>>,
37}
38
39pub struct StdinLock<'a> {
41 inner: MutexGuard<'a, BufReader<StdinRaw>>,
42}
43
44impl Stdin {
45 pub fn lock(&self) -> StdinLock<'static> {
52 StdinLock {
55 inner: self.inner.lock(),
56 }
57 }
58
59 #[cfg(feature = "alloc")]
61 pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
62 self.inner.lock().read_line(buf)
63 }
64}
65
66impl Read for Stdin {
67 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
69 let read_len = self.inner.lock().read(buf)?;
70 if buf.is_empty() || read_len > 0 {
71 return Ok(read_len);
72 }
73 loop {
75 let read_len = self.inner.lock().read(buf)?;
76 if read_len > 0 {
77 return Ok(read_len);
78 }
79 crate::thread::yield_now();
80 }
81 }
82}
83
84impl Read for StdinLock<'_> {
85 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
86 self.inner.read(buf)
87 }
88}
89
90impl BufRead for StdinLock<'_> {
91 fn fill_buf(&mut self) -> io::Result<&[u8]> {
92 self.inner.fill_buf()
93 }
94
95 fn consume(&mut self, n: usize) {
96 self.inner.consume(n)
97 }
98
99 #[cfg(feature = "alloc")]
100 fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
101 self.inner.read_until(byte, buf)
102 }
103
104 #[cfg(feature = "alloc")]
105 fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
106 self.inner.read_line(buf)
107 }
108}
109
110pub struct Stdout {
112 inner: &'static Mutex<StdoutRaw>,
113}
114
115pub struct StdoutLock<'a> {
117 inner: MutexGuard<'a, StdoutRaw>,
118}
119
120impl Stdout {
121 pub fn lock(&self) -> StdoutLock<'static> {
127 StdoutLock {
128 inner: self.inner.lock(),
129 }
130 }
131}
132
133impl Write for Stdout {
134 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
135 self.inner.lock().write(buf)
136 }
137 fn flush(&mut self) -> io::Result<()> {
138 self.inner.lock().flush()
139 }
140}
141
142impl Write for StdoutLock<'_> {
143 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
144 self.inner.write(buf)
145 }
146 fn flush(&mut self) -> io::Result<()> {
147 self.inner.flush()
148 }
149}
150
151pub fn stdin() -> Stdin {
153 static INSTANCE: Mutex<BufReader<StdinRaw>> = Mutex::new(BufReader::new(StdinRaw));
154 Stdin { inner: &INSTANCE }
155}
156
157pub fn stdout() -> Stdout {
159 static INSTANCE: Mutex<StdoutRaw> = Mutex::new(StdoutRaw);
160 Stdout { inner: &INSTANCE }
161}
162
163#[doc(hidden)]
164pub fn __print_impl(args: core::fmt::Arguments) {
165 if cfg!(feature = "smp") {
166 arceos_api::stdio::ax_console_write_fmt(args).unwrap();
169 } else {
170 stdout().lock().write_fmt(args).unwrap();
171 }
172}