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}