use core::fmt;
use crate::{fd::AsFd as _, io, sys};
pub fn stdin() -> io::Result<Stdin> {
sys::stdio::stdin().map(Stdin)
}
pub fn stdout() -> io::Result<Stdout> {
sys::stdio::stdout().map(Stdout)
}
pub fn stderr() -> io::Result<Stderr> {
sys::stdio::stderr().map(Stderr)
}
pub struct Stdin(sys::stdio::StdioFd);
pub struct Stdout(sys::stdio::StdioFd);
pub struct Stderr(sys::stdio::StdioFd);
impl_as_fd!(Stdin, Stdout, Stderr);
impl io::Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
sys::read(self.as_fd(), buf)
}
}
impl io::Write for Stdout {
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
sys::write(self.as_fd(), bytes)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl io::Write for Stderr {
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
sys::write(self.as_fd(), bytes)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl fmt::Debug for Stdin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Stdin").finish_non_exhaustive()
}
}
impl fmt::Debug for Stdout {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Stdout").finish_non_exhaustive()
}
}
impl fmt::Debug for Stderr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Stderr").finish_non_exhaustive()
}
}
pub trait IsTerminal: crate::sealed::Sealed {
#[doc(alias = "isatty")]
#[doc(alias = "SYS_ISTTY")] fn is_terminal(&self) -> bool;
}
macro_rules! impl_is_terminal {
($($t:ty),*$(,)?) => {$(
impl crate::sealed::Sealed for $t {}
impl crate::io::IsTerminal for $t {
#[inline]
fn is_terminal(&self) -> bool {
use crate::fd::AsFd as _;
crate::sys::stdio::is_terminal(self.as_fd())
}
}
)*}
}
impl_is_terminal!(Stdin, Stdout, Stderr);
#[cfg(feature = "fs")]
impl_is_terminal!(crate::fs::File);