use crate::io::{self, prelude::*, BufReader};
use crate::sync::{Mutex, MutexGuard};
#[cfg(feature = "alloc")]
use alloc::{string::String, vec::Vec};
struct StdinRaw;
struct StdoutRaw;
impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut read_len = 0;
while read_len < buf.len() {
if let Some(c) = arceos_api::stdio::ax_console_read_byte() {
buf[read_len] = c;
read_len += 1;
} else {
break;
}
}
Ok(read_len)
}
}
impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
arceos_api::stdio::ax_console_write_bytes(buf)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
pub struct Stdin {
inner: &'static Mutex<BufReader<StdinRaw>>,
}
pub struct StdinLock<'a> {
inner: MutexGuard<'a, BufReader<StdinRaw>>,
}
impl Stdin {
pub fn lock(&self) -> StdinLock<'static> {
StdinLock {
inner: self.inner.lock(),
}
}
#[cfg(feature = "alloc")]
pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
self.inner.lock().read_line(buf)
}
}
impl Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let read_len = self.inner.lock().read(buf)?;
if buf.is_empty() || read_len > 0 {
return Ok(read_len);
}
loop {
let read_len = self.inner.lock().read(buf)?;
if read_len > 0 {
return Ok(read_len);
}
crate::thread::yield_now();
}
}
}
impl Read for StdinLock<'_> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}
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)
}
#[cfg(feature = "alloc")]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_until(byte, buf)
}
#[cfg(feature = "alloc")]
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
self.inner.read_line(buf)
}
}
pub struct Stdout {
inner: &'static Mutex<StdoutRaw>,
}
pub struct StdoutLock<'a> {
inner: MutexGuard<'a, StdoutRaw>,
}
impl Stdout {
pub fn lock(&self) -> StdoutLock<'static> {
StdoutLock {
inner: self.inner.lock(),
}
}
}
impl Write for Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.lock().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.lock().flush()
}
}
impl Write for StdoutLock<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}
pub fn stdin() -> Stdin {
static INSTANCE: Mutex<BufReader<StdinRaw>> = Mutex::new(BufReader::new(StdinRaw));
Stdin { inner: &INSTANCE }
}
pub fn stdout() -> Stdout {
static INSTANCE: Mutex<StdoutRaw> = Mutex::new(StdoutRaw);
Stdout { inner: &INSTANCE }
}
#[doc(hidden)]
pub fn __print_impl(args: core::fmt::Arguments) {
if cfg!(feature = "smp") {
arceos_api::stdio::ax_console_write_fmt(args).unwrap();
} else {
stdout().lock().write_fmt(args).unwrap();
}
}