WasiFile: all operations are now async

only fn as_any(&self) -> &dyn Any doesnt get to be async.
This commit is contained in:
Pat Hickey
2021-04-14 15:17:31 -07:00
parent 025a1ecff4
commit 00e58567d9
4 changed files with 114 additions and 75 deletions

View File

@@ -4,30 +4,38 @@ use std::any::Any;
use std::cell::{Ref, RefMut};
use std::ops::{Deref, DerefMut};
#[wiggle::async_trait]
pub trait WasiFile {
fn as_any(&self) -> &dyn Any;
fn datasync(&self) -> Result<(), Error>; // write op
fn sync(&self) -> Result<(), Error>; // file op
fn get_filetype(&self) -> Result<FileType, Error>; // file op
fn get_fdflags(&self) -> Result<FdFlags, Error>; // file op
fn set_fdflags(&mut self, flags: FdFlags) -> Result<(), Error>; // file op
fn get_filestat(&self) -> Result<Filestat, Error>; // split out get_length as a read & write op, rest is a file op
fn set_filestat_size(&self, _size: u64) -> Result<(), Error>; // write op
fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error>; // file op
fn allocate(&self, offset: u64, len: u64) -> Result<(), Error>; // write op
fn set_times(
async fn datasync(&self) -> Result<(), Error>; // write op
async fn sync(&self) -> Result<(), Error>; // file op
async fn get_filetype(&self) -> Result<FileType, Error>; // file op
async fn get_fdflags(&self) -> Result<FdFlags, Error>; // file op
async fn set_fdflags(&mut self, flags: FdFlags) -> Result<(), Error>; // file op
async fn get_filestat(&self) -> Result<Filestat, Error>; // split out get_length as a read & write op, rest is a file op
async fn set_filestat_size(&self, _size: u64) -> Result<(), Error>; // write op
async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error>; // file op
async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error>; // write op
async fn set_times(
&self,
atime: Option<SystemTimeSpec>,
mtime: Option<SystemTimeSpec>,
) -> Result<(), Error>;
fn read_vectored(&self, bufs: &mut [std::io::IoSliceMut]) -> Result<u64, Error>; // read op
fn read_vectored_at(&self, bufs: &mut [std::io::IoSliceMut], offset: u64)
-> Result<u64, Error>; // file op
fn write_vectored(&self, bufs: &[std::io::IoSlice]) -> Result<u64, Error>; // write op
fn write_vectored_at(&self, bufs: &[std::io::IoSlice], offset: u64) -> Result<u64, Error>; // file op
fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error>; // file op that generates a new stream from a file will supercede this
fn peek(&self, buf: &mut [u8]) -> Result<u64, Error>; // read op
fn num_ready_bytes(&self) -> Result<u64, Error>; // read op
async fn read_vectored<'a>(&self, bufs: &mut [std::io::IoSliceMut<'a>]) -> Result<u64, Error>; // read op
async fn read_vectored_at<'a>(
&self,
bufs: &mut [std::io::IoSliceMut<'a>],
offset: u64,
) -> Result<u64, Error>; // file op
async fn write_vectored<'a>(&self, bufs: &[std::io::IoSlice<'a>]) -> Result<u64, Error>; // write op
async fn write_vectored_at<'a>(
&self,
bufs: &[std::io::IoSlice<'a>],
offset: u64,
) -> Result<u64, Error>; // file op
async fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error>; // file op that generates a new stream from a file will supercede this
async fn peek(&self, buf: &mut [u8]) -> Result<u64, Error>; // read op
async fn num_ready_bytes(&self) -> Result<u64, Error>; // read op
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -111,11 +119,11 @@ impl FileEntry {
Ok(())
}
pub fn get_fdstat(&self) -> Result<FdStat, Error> {
pub async fn get_fdstat(&self) -> Result<FdStat, Error> {
Ok(FdStat {
filetype: self.file.get_filetype()?,
filetype: self.file.get_filetype().await?,
caps: self.caps,
flags: self.file.get_fdflags()?,
flags: self.file.get_fdflags().await?,
})
}
}

View File

@@ -105,30 +105,31 @@ impl From<&str> for ReadPipe<io::Cursor<String>> {
}
}
#[wiggle::async_trait]
impl<R: Read + Any> WasiFile for ReadPipe<R> {
fn as_any(&self) -> &dyn Any {
self
}
fn datasync(&self) -> Result<(), Error> {
async fn datasync(&self) -> Result<(), Error> {
Ok(()) // trivial: no implementation needed
}
fn sync(&self) -> Result<(), Error> {
async fn sync(&self) -> Result<(), Error> {
Ok(()) // trivial
}
fn get_filetype(&self) -> Result<FileType, Error> {
async fn get_filetype(&self) -> Result<FileType, Error> {
Ok(FileType::Pipe)
}
fn get_fdflags(&self) -> Result<FdFlags, Error> {
async fn get_fdflags(&self) -> Result<FdFlags, Error> {
Ok(FdFlags::empty())
}
fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> {
async fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> {
Err(Error::badf())
}
fn get_filestat(&self) -> Result<Filestat, Error> {
async fn get_filestat(&self) -> Result<Filestat, Error> {
Ok(Filestat {
device_id: 0,
inode: 0,
filetype: self.get_filetype()?,
filetype: self.get_filetype().await?,
nlink: 0,
size: 0, // XXX no way to get a size out of a Read :(
atim: None,
@@ -136,42 +137,50 @@ impl<R: Read + Any> WasiFile for ReadPipe<R> {
ctim: None,
})
}
fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
Err(Error::badf())
}
fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
Err(Error::badf())
}
fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> {
async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> {
Err(Error::badf())
}
fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> {
async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {
let n = self.borrow().read_vectored(bufs)?;
Ok(n.try_into()?)
}
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut], offset: u64) -> Result<u64, Error> {
async fn read_vectored_at<'a>(
&self,
bufs: &mut [io::IoSliceMut<'a>],
offset: u64,
) -> Result<u64, Error> {
Err(Error::badf())
}
fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result<u64, Error> {
async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
Err(Error::badf())
}
fn write_vectored_at(&self, bufs: &[io::IoSlice], offset: u64) -> Result<u64, Error> {
async fn write_vectored_at<'a>(
&self,
bufs: &[io::IoSlice<'a>],
offset: u64,
) -> Result<u64, Error> {
Err(Error::badf())
}
fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
async fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
Err(Error::badf())
}
fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
async fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
Err(Error::badf())
}
fn set_times(
async fn set_times(
&self,
atime: Option<SystemTimeSpec>,
mtime: Option<SystemTimeSpec>,
) -> Result<(), Error> {
Err(Error::badf())
}
fn num_ready_bytes(&self) -> Result<u64, Error> {
async fn num_ready_bytes(&self) -> Result<u64, Error> {
Ok(0)
}
}
@@ -249,30 +258,31 @@ impl WritePipe<io::Cursor<Vec<u8>>> {
}
}
#[wiggle::async_trait]
impl<W: Write + Any> WasiFile for WritePipe<W> {
fn as_any(&self) -> &dyn Any {
self
}
fn datasync(&self) -> Result<(), Error> {
async fn datasync(&self) -> Result<(), Error> {
Ok(())
}
fn sync(&self) -> Result<(), Error> {
async fn sync(&self) -> Result<(), Error> {
Ok(())
}
fn get_filetype(&self) -> Result<FileType, Error> {
async fn get_filetype(&self) -> Result<FileType, Error> {
Ok(FileType::Pipe)
}
fn get_fdflags(&self) -> Result<FdFlags, Error> {
async fn get_fdflags(&self) -> Result<FdFlags, Error> {
Ok(FdFlags::APPEND)
}
fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> {
async fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> {
Err(Error::badf())
}
fn get_filestat(&self) -> Result<Filestat, Error> {
async fn get_filestat(&self) -> Result<Filestat, Error> {
Ok(Filestat {
device_id: 0,
inode: 0,
filetype: self.get_filetype()?,
filetype: self.get_filetype().await?,
nlink: 0,
size: 0, // XXX no way to get a size out of a Write :(
atim: None,
@@ -280,42 +290,50 @@ impl<W: Write + Any> WasiFile for WritePipe<W> {
ctim: None,
})
}
fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
Err(Error::badf())
}
fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
Err(Error::badf())
}
fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> {
async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> {
Err(Error::badf())
}
fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> {
async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {
Err(Error::badf())
}
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut], offset: u64) -> Result<u64, Error> {
async fn read_vectored_at<'a>(
&self,
bufs: &mut [io::IoSliceMut<'a>],
offset: u64,
) -> Result<u64, Error> {
Err(Error::badf())
}
fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result<u64, Error> {
async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
let n = self.borrow().write_vectored(bufs)?;
Ok(n.try_into()?)
}
fn write_vectored_at(&self, bufs: &[io::IoSlice], offset: u64) -> Result<u64, Error> {
async fn write_vectored_at<'a>(
&self,
bufs: &[io::IoSlice<'a>],
offset: u64,
) -> Result<u64, Error> {
Err(Error::badf())
}
fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
async fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
Err(Error::badf())
}
fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
async fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
Err(Error::badf())
}
fn set_times(
async fn set_times(
&self,
atime: Option<SystemTimeSpec>,
mtime: Option<SystemTimeSpec>,
) -> Result<(), Error> {
Err(Error::badf())
}
fn num_ready_bytes(&self) -> Result<u64, Error> {
async fn num_ready_bytes(&self) -> Result<u64, Error> {
Ok(0)
}
}

View File

@@ -422,7 +422,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
Ok(Snapshot1::fd_filestat_get(self, fd.into())?.into()).await
Ok(Snapshot1::fd_filestat_get(self, fd.into()).await?.into())
}
async fn fd_filestat_set_size(
@@ -473,7 +473,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
.map(|s| IoSliceMut::new(&mut *s))
.collect();
let bytes_read = f.read_vectored(&mut ioslices)?;
let bytes_read = f.read_vectored(&mut ioslices).await?;
Ok(types::Size::try_from(bytes_read)?)
}
@@ -502,7 +502,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
.map(|s| IoSliceMut::new(&mut *s))
.collect();
let bytes_read = f.read_vectored_at(&mut ioslices, offset)?;
let bytes_read = f.read_vectored_at(&mut ioslices, offset).await?;
Ok(types::Size::try_from(bytes_read)?)
}
@@ -527,7 +527,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
.iter()
.map(|s| IoSlice::new(s.deref()))
.collect();
let bytes_written = f.write_vectored(&ioslices)?;
let bytes_written = f.write_vectored(&ioslices).await?;
Ok(types::Size::try_from(bytes_written)?)
}
@@ -556,7 +556,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
.iter()
.map(|s| IoSlice::new(s.deref()))
.collect();
let bytes_written = f.write_vectored_at(&ioslices, offset)?;
let bytes_written = f.write_vectored_at(&ioslices, offset).await?;
Ok(types::Size::try_from(bytes_written)?)
}

View File

@@ -22,6 +22,9 @@ use wiggle::GuestPtr;
wiggle::from_witx!({
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
errors: { errno => Error },
// Note: not every function actually needs to be async, however, nearly all of them do, and
// keeping that set the same in this macro and the wasmtime_wiggle / lucet_wiggle macros is
// tedious, and there is no cost to having a sync function be async in this case.
async: *
});
@@ -261,7 +264,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
self.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::ADVISE)?
.advise(offset, len, advice.into())?;
.advise(offset, len, advice.into())
.await?;
Ok(())
}
@@ -274,7 +278,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
self.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::ALLOCATE)?
.allocate(offset, len)?;
.allocate(offset, len)
.await?;
Ok(())
}
@@ -308,7 +313,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
self.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::DATASYNC)?
.datasync()?;
.datasync()
.await?;
Ok(())
}
@@ -317,7 +323,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let fd = u32::from(fd);
if table.is::<FileEntry>(fd) {
let file_entry: Ref<FileEntry> = table.get(fd)?;
let fdstat = file_entry.get_fdstat()?;
let fdstat = file_entry.get_fdstat().await?;
Ok(types::Fdstat::from(&fdstat))
} else if table.is::<DirEntry>(fd) {
let dir_entry: Ref<DirEntry> = table.get(fd)?;
@@ -333,6 +339,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.get_file_mut(u32::from(fd))?
.get_cap(FileCaps::FDSTAT_SET_FLAGS)?
.set_fdflags(FdFlags::from(flags))
.await
}
async fn fd_fdstat_set_rights(
@@ -364,7 +371,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let filestat = table
.get_file(fd)?
.get_cap(FileCaps::FILESTAT_GET)?
.get_filestat()?;
.get_filestat()
.await?;
Ok(filestat.into())
} else if table.is::<DirEntry>(fd) {
let filestat = table
@@ -385,7 +393,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
self.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::FILESTAT_SET_SIZE)?
.set_filestat_size(size)?;
.set_filestat_size(size)
.await?;
Ok(())
}
@@ -413,6 +422,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.expect("checked that entry is file")
.get_cap(FileCaps::FILESTAT_SET_TIMES)?
.set_times(atim, mtim)
.await
} else if table.is::<DirEntry>(fd) {
table
.get_dir(fd)
@@ -446,7 +456,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.map(|s| IoSliceMut::new(&mut *s))
.collect();
let bytes_read = f.read_vectored(&mut ioslices)?;
let bytes_read = f.read_vectored(&mut ioslices).await?;
Ok(types::Size::try_from(bytes_read)?)
}
@@ -475,7 +485,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.map(|s| IoSliceMut::new(&mut *s))
.collect();
let bytes_read = f.read_vectored_at(&mut ioslices, offset)?;
let bytes_read = f.read_vectored_at(&mut ioslices, offset).await?;
Ok(types::Size::try_from(bytes_read)?)
}
@@ -500,7 +510,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.iter()
.map(|s| IoSlice::new(s.deref()))
.collect();
let bytes_written = f.write_vectored(&ioslices)?;
let bytes_written = f.write_vectored(&ioslices).await?;
Ok(types::Size::try_from(bytes_written)?)
}
@@ -529,7 +539,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.iter()
.map(|s| IoSlice::new(s.deref()))
.collect();
let bytes_written = f.write_vectored_at(&ioslices, offset)?;
let bytes_written = f.write_vectored_at(&ioslices, offset).await?;
Ok(types::Size::try_from(bytes_written)?)
}
@@ -610,7 +620,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.table()
.get_file(u32::from(fd))?
.get_cap(required_caps)?
.seek(whence)?;
.seek(whence)
.await?;
Ok(newoffset)
}
@@ -618,7 +629,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
self.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::SYNC)?
.sync()?;
.sync()
.await?;
Ok(())
}
@@ -628,7 +640,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::TELL)?
.seek(std::io::SeekFrom::Current(0))?;
.seek(std::io::SeekFrom::Current(0))
.await?;
Ok(offset)
}