Path: blob/main/crates/wasi-common/src/sync/stdio.rs
1693 views
use crate::sync::file::convert_systimespec;1use fs_set_times::SetTimes;2use std::any::Any;3use std::io::{self, IsTerminal, Read, Write};4use system_interface::io::ReadReady;56use crate::{7Error, ErrorExt,8file::{FdFlags, FileType, WasiFile},9};10#[cfg(windows)]11use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};12#[cfg(unix)]13use io_lifetimes::{AsFd, BorrowedFd};14#[cfg(windows)]15use io_lifetimes::{AsHandle, BorrowedHandle};1617pub struct Stdin(std::io::Stdin);1819pub fn stdin() -> Stdin {20Stdin(std::io::stdin())21}2223#[wiggle::async_trait]24impl WasiFile for Stdin {25fn as_any(&self) -> &dyn Any {26self27}2829#[cfg(unix)]30fn pollable(&self) -> Option<rustix::fd::BorrowedFd<'_>> {31Some(self.0.as_fd())32}3334#[cfg(windows)]35fn pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket> {36Some(self.0.as_raw_handle_or_socket())37}3839async fn get_filetype(&self) -> Result<FileType, Error> {40if self.isatty() {41Ok(FileType::CharacterDevice)42} else {43Ok(FileType::Unknown)44}45}46async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {47let n = self.0.lock().read_vectored(bufs)?;48Ok(n.try_into().map_err(|_| Error::range())?)49}50async fn read_vectored_at<'a>(51&self,52_bufs: &mut [io::IoSliceMut<'a>],53_offset: u64,54) -> Result<u64, Error> {55Err(Error::seek_pipe())56}57async fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> {58Err(Error::seek_pipe())59}60async fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> {61Err(Error::seek_pipe())62}63async fn set_times(64&self,65atime: Option<crate::SystemTimeSpec>,66mtime: Option<crate::SystemTimeSpec>,67) -> Result<(), Error> {68self.069.set_times(convert_systimespec(atime), convert_systimespec(mtime))?;70Ok(())71}72fn num_ready_bytes(&self) -> Result<u64, Error> {73Ok(self.0.num_ready_bytes()?)74}75fn isatty(&self) -> bool {76#[cfg(unix)]77return self.0.as_fd().is_terminal();78#[cfg(windows)]79return self.0.as_handle().is_terminal();80}81}82#[cfg(windows)]83impl AsHandle for Stdin {84fn as_handle(&self) -> BorrowedHandle<'_> {85self.0.as_handle()86}87}88#[cfg(windows)]89impl AsRawHandleOrSocket for Stdin {90#[inline]91fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {92self.0.as_raw_handle_or_socket()93}94}95#[cfg(unix)]96impl AsFd for Stdin {97fn as_fd(&self) -> BorrowedFd<'_> {98self.0.as_fd()99}100}101102macro_rules! wasi_file_write_impl {103($ty:ty, $ident:ident) => {104#[wiggle::async_trait]105impl WasiFile for $ty {106fn as_any(&self) -> &dyn Any {107self108}109#[cfg(unix)]110fn pollable(&self) -> Option<rustix::fd::BorrowedFd<'_>> {111Some(self.0.as_fd())112}113#[cfg(windows)]114fn pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket> {115Some(self.0.as_raw_handle_or_socket())116}117async fn get_filetype(&self) -> Result<FileType, Error> {118if self.isatty() {119Ok(FileType::CharacterDevice)120} else {121Ok(FileType::Unknown)122}123}124async fn get_fdflags(&self) -> Result<FdFlags, Error> {125Ok(FdFlags::APPEND)126}127async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {128let mut io = self.0.lock();129let n = io.write_vectored(bufs)?;130// On a successful write additionally flush out the bytes to131// handle stdio buffering done by libstd since WASI interfaces132// here aren't buffered.133io.flush()?;134Ok(n.try_into().map_err(|_| {135Error::range().context("converting write_vectored total length")136})?)137}138async fn write_vectored_at<'a>(139&self,140_bufs: &[io::IoSlice<'a>],141_offset: u64,142) -> Result<u64, Error> {143Err(Error::seek_pipe())144}145async fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> {146Err(Error::seek_pipe())147}148async fn set_times(149&self,150atime: Option<crate::SystemTimeSpec>,151mtime: Option<crate::SystemTimeSpec>,152) -> Result<(), Error> {153self.0154.set_times(convert_systimespec(atime), convert_systimespec(mtime))?;155Ok(())156}157fn isatty(&self) -> bool {158self.0.is_terminal()159}160}161#[cfg(windows)]162impl AsHandle for $ty {163fn as_handle(&self) -> BorrowedHandle<'_> {164self.0.as_handle()165}166}167#[cfg(unix)]168impl AsFd for $ty {169fn as_fd(&self) -> BorrowedFd<'_> {170self.0.as_fd()171}172}173#[cfg(windows)]174impl AsRawHandleOrSocket for $ty {175#[inline]176fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {177self.0.as_raw_handle_or_socket()178}179}180};181}182183pub struct Stdout(std::io::Stdout);184185pub fn stdout() -> Stdout {186Stdout(std::io::stdout())187}188wasi_file_write_impl!(Stdout, Stdout);189190pub struct Stderr(std::io::Stderr);191192pub fn stderr() -> Stderr {193Stderr(std::io::stderr())194}195wasi_file_write_impl!(Stderr, Stderr);196197198