Implement RFC 11: Redesigning Wasmtime's APIs (#2897)

Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
This commit is contained in:
Alex Crichton
2021-06-03 09:10:53 -05:00
committed by GitHub
parent a5a28b1c5b
commit 7a1b7cdf92
233 changed files with 13349 additions and 11997 deletions

View File

@@ -6,25 +6,23 @@ use crate::string_array::{StringArray, StringArrayError};
use crate::table::Table;
use crate::Error;
use cap_rand::RngCore;
use std::cell::{RefCell, RefMut};
use std::path::{Path, PathBuf};
use std::rc::Rc;
pub struct WasiCtx {
pub args: StringArray,
pub env: StringArray,
pub random: RefCell<Box<dyn RngCore>>,
pub random: Box<dyn RngCore + Send + Sync>,
pub clocks: WasiClocks,
pub sched: Box<dyn WasiSched>,
pub table: Rc<RefCell<Table>>,
pub table: Table,
}
impl WasiCtx {
pub fn new(
random: RefCell<Box<dyn RngCore>>,
random: Box<dyn RngCore + Send + Sync>,
clocks: WasiClocks,
sched: Box<dyn WasiSched>,
table: Rc<RefCell<Table>>,
table: Table,
) -> Self {
let mut s = WasiCtx {
args: StringArray::new(),
@@ -40,13 +38,13 @@ impl WasiCtx {
s
}
pub fn insert_file(&self, fd: u32, file: Box<dyn WasiFile>, caps: FileCaps) {
pub fn insert_file(&mut self, fd: u32, file: Box<dyn WasiFile>, caps: FileCaps) {
self.table()
.insert_at(fd, Box::new(FileEntry::new(caps, file)));
}
pub fn insert_dir(
&self,
&mut self,
fd: u32,
dir: Box<dyn WasiDir>,
caps: DirCaps,
@@ -59,8 +57,8 @@ impl WasiCtx {
);
}
pub fn table(&self) -> RefMut<Table> {
self.table.borrow_mut()
pub fn table(&mut self) -> &mut Table {
&mut self.table
}
pub fn push_arg(&mut self, arg: &str) -> Result<(), StringArrayError> {

View File

@@ -2,8 +2,6 @@ use crate::file::{FdFlags, FileCaps, FileType, Filestat, OFlags, WasiFile};
use crate::{Error, ErrorExt, SystemTimeSpec};
use bitflags::bitflags;
use std::any::Any;
use std::cell::Ref;
use std::ops::Deref;
use std::path::PathBuf;
#[wiggle::async_trait]
@@ -113,14 +111,14 @@ impl DirEntry {
}
}
pub trait DirEntryExt<'a> {
fn get_cap(self, caps: DirCaps) -> Result<Ref<'a, dyn WasiDir>, Error>;
pub trait DirEntryExt {
fn get_cap(&self, caps: DirCaps) -> Result<&dyn WasiDir, Error>;
}
impl<'a> DirEntryExt<'a> for Ref<'a, DirEntry> {
fn get_cap(self, caps: DirCaps) -> Result<Ref<'a, dyn WasiDir>, Error> {
impl DirEntryExt for DirEntry {
fn get_cap(&self, caps: DirCaps) -> Result<&dyn WasiDir, Error> {
self.capable_of_dir(caps)?;
Ok(Ref::map(self, |r| r.dir.deref()))
Ok(&*self.dir)
}
}
@@ -152,17 +150,17 @@ pub struct DirFdStat {
}
pub(crate) trait TableDirExt {
fn get_dir(&self, fd: u32) -> Result<Ref<DirEntry>, Error>;
fn get_dir(&self, fd: u32) -> Result<&DirEntry, Error>;
fn is_preopen(&self, fd: u32) -> bool;
}
impl TableDirExt for crate::table::Table {
fn get_dir(&self, fd: u32) -> Result<Ref<DirEntry>, Error> {
fn get_dir(&self, fd: u32) -> Result<&DirEntry, Error> {
self.get(fd)
}
fn is_preopen(&self, fd: u32) -> bool {
if self.is::<DirEntry>(fd) {
let dir_entry: std::cell::Ref<DirEntry> = self.get(fd).unwrap();
let dir_entry: &DirEntry = self.get(fd).unwrap();
dir_entry.preopen_path.is_some()
} else {
false

View File

@@ -1,11 +1,9 @@
use crate::{Error, ErrorExt, SystemTimeSpec};
use bitflags::bitflags;
use std::any::Any;
use std::cell::{Ref, RefMut};
use std::ops::{Deref, DerefMut};
#[wiggle::async_trait]
pub trait WasiFile: Send {
pub trait WasiFile: Send + Sync {
fn as_any(&self) -> &dyn Any;
async fn datasync(&self) -> Result<(), Error>; // write op
async fn sync(&self) -> Result<(), Error>; // file op
@@ -37,8 +35,8 @@ pub trait WasiFile: Send {
async fn peek(&self, buf: &mut [u8]) -> Result<u64, Error>; // read op
async fn num_ready_bytes(&self) -> Result<u64, Error>; // read op
async fn readable(&mut self) -> Result<(), Error>;
async fn writable(&mut self) -> Result<(), Error>;
async fn readable(&self) -> Result<(), Error>;
async fn writable(&self) -> Result<(), Error>;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -86,14 +84,14 @@ pub struct Filestat {
}
pub(crate) trait TableFileExt {
fn get_file(&self, fd: u32) -> Result<Ref<FileEntry>, Error>;
fn get_file_mut(&self, fd: u32) -> Result<RefMut<FileEntry>, Error>;
fn get_file(&self, fd: u32) -> Result<&FileEntry, Error>;
fn get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error>;
}
impl TableFileExt for crate::table::Table {
fn get_file(&self, fd: u32) -> Result<Ref<FileEntry>, Error> {
fn get_file(&self, fd: u32) -> Result<&FileEntry, Error> {
self.get(fd)
}
fn get_file_mut(&self, fd: u32) -> Result<RefMut<FileEntry>, Error> {
fn get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error> {
self.get_mut(fd)
}
}
@@ -131,24 +129,20 @@ impl FileEntry {
}
}
pub trait FileEntryExt<'a> {
fn get_cap(self, caps: FileCaps) -> Result<Ref<'a, dyn WasiFile>, Error>;
pub trait FileEntryExt {
fn get_cap(&self, caps: FileCaps) -> Result<&dyn WasiFile, Error>;
fn get_cap_mut(&mut self, caps: FileCaps) -> Result<&mut dyn WasiFile, Error>;
}
impl<'a> FileEntryExt<'a> for Ref<'a, FileEntry> {
fn get_cap(self, caps: FileCaps) -> Result<Ref<'a, dyn WasiFile>, Error> {
impl FileEntryExt for FileEntry {
fn get_cap(&self, caps: FileCaps) -> Result<&dyn WasiFile, Error> {
self.capable_of(caps)?;
Ok(Ref::map(self, |r| r.file.deref()))
Ok(&*self.file)
}
}
pub trait FileEntryMutExt<'a> {
fn get_cap(self, caps: FileCaps) -> Result<RefMut<'a, dyn WasiFile>, Error>;
}
impl<'a> FileEntryMutExt<'a> for RefMut<'a, FileEntry> {
fn get_cap(self, caps: FileCaps) -> Result<RefMut<'a, dyn WasiFile>, Error> {
fn get_cap_mut(&mut self, caps: FileCaps) -> Result<&mut dyn WasiFile, Error> {
self.capable_of(caps)?;
Ok(RefMut::map(self, |r| r.file.deref_mut()))
Ok(&mut *self.file)
}
}

View File

@@ -23,15 +23,13 @@ use std::sync::{Arc, RwLock};
/// A variety of `From` impls are provided so that common pipe types are easy to create. For example:
///
/// ```no_run
/// # use std::rc::Rc;
/// # use std::cell::RefCell;
/// use wasi_common::{pipe::ReadPipe, WasiCtx, Table};
/// let stdin = ReadPipe::from("hello from stdin!");
/// // Brint these instances from elsewhere (e.g. wasi-cap-std-sync):
/// let random = todo!();
/// let clocks = todo!();
/// let sched = todo!();
/// let table = Rc::new(RefCell::new(Table::new()));
/// let table = Table::new();
/// let mut ctx = WasiCtx::new(random, clocks, sched, table);
/// ctx.set_stdin(Box::new(stdin.clone()));
/// ```
@@ -182,10 +180,10 @@ impl<R: Read + Any + Send + Sync> WasiFile for ReadPipe<R> {
async fn num_ready_bytes(&self) -> Result<u64, Error> {
Ok(0)
}
async fn readable(&mut self) -> Result<(), Error> {
async fn readable(&self) -> Result<(), Error> {
Err(Error::badf())
}
async fn writable(&mut self) -> Result<(), Error> {
async fn writable(&self) -> Result<(), Error> {
Err(Error::badf())
}
}
@@ -193,15 +191,13 @@ impl<R: Read + Any + Send + Sync> WasiFile for ReadPipe<R> {
/// A virtual pipe write end.
///
/// ```no_run
/// # use std::rc::Rc;
/// # use std::cell::RefCell;
/// use wasi_common::{pipe::WritePipe, WasiCtx, Table};
/// let stdout = WritePipe::new_in_memory();
/// // Brint these instances from elsewhere (e.g. wasi-cap-std-sync):
/// let random = todo!();
/// let clocks = todo!();
/// let sched = todo!();
/// let table = Rc::new(RefCell::new(Table::new()));
/// let table = Table::new();
/// let mut ctx = WasiCtx::new(random, clocks, sched, table);
/// ctx.set_stdout(Box::new(stdout.clone()));
/// // use ctx in an instance, then make sure it is dropped:
@@ -340,10 +336,10 @@ impl<W: Write + Any + Send + Sync> WasiFile for WritePipe<W> {
async fn num_ready_bytes(&self) -> Result<u64, Error> {
Ok(0)
}
async fn readable(&mut self) -> Result<(), Error> {
async fn readable(&self) -> Result<(), Error> {
Err(Error::badf())
}
async fn writable(&mut self) -> Result<(), Error> {
async fn writable(&self) -> Result<(), Error> {
Err(Error::badf())
}
}

View File

@@ -10,7 +10,7 @@ pub use subscription::{
};
#[wiggle::async_trait]
pub trait WasiSched {
pub trait WasiSched: Send + Sync {
async fn poll_oneoff<'a>(&self, poll: &mut Poll<'a>) -> Result<(), Error>;
async fn sched_yield(&self) -> Result<(), Error>;
async fn sleep(&self, duration: Duration) -> Result<(), Error>;
@@ -56,11 +56,11 @@ impl<'a> Poll<'a> {
ud,
));
}
pub fn subscribe_read(&mut self, file: &'a mut dyn WasiFile, ud: Userdata) {
pub fn subscribe_read(&mut self, file: &'a dyn WasiFile, ud: Userdata) {
self.subs
.push((Subscription::Read(RwSubscription::new(file)), ud));
}
pub fn subscribe_write(&mut self, file: &'a mut dyn WasiFile, ud: Userdata) {
pub fn subscribe_write(&mut self, file: &'a dyn WasiFile, ud: Userdata) {
self.subs
.push((Subscription::Write(RwSubscription::new(file)), ud));
}

View File

@@ -3,7 +3,6 @@ use crate::file::WasiFile;
use crate::Error;
use bitflags::bitflags;
use cap_std::time::{Duration, Instant};
use std::cell::Cell;
bitflags! {
pub struct RwEventFlags: u32 {
@@ -12,24 +11,21 @@ bitflags! {
}
pub struct RwSubscription<'a> {
pub file: &'a mut dyn WasiFile,
status: Cell<Option<Result<(u64, RwEventFlags), Error>>>,
pub file: &'a dyn WasiFile,
status: Option<Result<(u64, RwEventFlags), Error>>,
}
impl<'a> RwSubscription<'a> {
pub fn new(file: &'a mut dyn WasiFile) -> Self {
Self {
file,
status: Cell::new(None),
}
pub fn new(file: &'a dyn WasiFile) -> Self {
Self { file, status: None }
}
pub fn complete(&self, size: u64, flags: RwEventFlags) {
self.status.set(Some(Ok((size, flags))))
pub fn complete(&mut self, size: u64, flags: RwEventFlags) {
self.status = Some(Ok((size, flags)))
}
pub fn error(&self, error: Error) {
self.status.set(Some(Err(error)))
pub fn error(&mut self, error: Error) {
self.status = Some(Err(error))
}
pub fn result(&self) -> Option<Result<(u64, RwEventFlags), Error>> {
pub fn result(&mut self) -> Option<Result<(u64, RwEventFlags), Error>> {
self.status.take()
}
}
@@ -72,8 +68,8 @@ pub enum SubscriptionResult {
impl SubscriptionResult {
pub fn from_subscription(s: Subscription) -> Option<SubscriptionResult> {
match s {
Subscription::Read(s) => s.result().map(SubscriptionResult::Read),
Subscription::Write(s) => s.result().map(SubscriptionResult::Write),
Subscription::Read(mut s) => s.result().map(SubscriptionResult::Read),
Subscription::Write(mut s) => s.result().map(SubscriptionResult::Write),
Subscription::MonotonicClock(s) => s.result().map(SubscriptionResult::MonotonicClock),
}
}

View File

@@ -1,4 +1,4 @@
use crate::file::{FileCaps, FileEntryExt, FileEntryMutExt, TableFileExt, WasiFile};
use crate::file::{FileCaps, FileEntryExt, TableFileExt};
use crate::sched::{
subscription::{RwEventFlags, SubscriptionResult},
Poll, Userdata,
@@ -7,7 +7,6 @@ use crate::snapshots::preview_1::types as snapshot1_types;
use crate::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1 as Snapshot1;
use crate::{Error, ErrorExt, WasiCtx};
use cap_std::time::Duration;
use std::cell::RefMut;
use std::collections::HashSet;
use std::convert::{TryFrom, TryInto};
use std::io::{IoSlice, IoSliceMut};
@@ -19,6 +18,7 @@ wiggle::from_witx!({
witx: ["$WASI_ROOT/phases/old/snapshot_0/witx/wasi_unstable.witx"],
errors: { errno => Error },
async: *,
wasmtime: false,
});
impl wiggle::GuestErrorType for types::Errno {
@@ -28,7 +28,7 @@ impl wiggle::GuestErrorType for types::Errno {
}
impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&self, e: Error) -> Result<types::Errno, wiggle::Trap> {
fn errno_from_error(&mut self, e: Error) -> Result<types::Errno, wiggle::Trap> {
debug!("Error: {:?}", e);
e.try_into()
.map_err(|e| wiggle::Trap::String(format!("{:?}", e)))
@@ -338,35 +338,35 @@ convert_flags_bidirectional!(
#[wiggle::async_trait]
impl wasi_unstable::WasiUnstable for WasiCtx {
async fn args_get<'a>(
&self,
&mut self,
argv: &GuestPtr<'a, GuestPtr<'a, u8>>,
argv_buf: &GuestPtr<'a, u8>,
) -> Result<(), Error> {
Snapshot1::args_get(self, argv, argv_buf).await
}
async fn args_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
async fn args_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
Snapshot1::args_sizes_get(self).await
}
async fn environ_get<'a>(
&self,
&mut self,
environ: &GuestPtr<'a, GuestPtr<'a, u8>>,
environ_buf: &GuestPtr<'a, u8>,
) -> Result<(), Error> {
Snapshot1::environ_get(self, environ, environ_buf).await
}
async fn environ_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
async fn environ_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
Snapshot1::environ_sizes_get(self).await
}
async fn clock_res_get(&self, id: types::Clockid) -> Result<types::Timestamp, Error> {
async fn clock_res_get(&mut self, id: types::Clockid) -> Result<types::Timestamp, Error> {
Snapshot1::clock_res_get(self, id.into()).await
}
async fn clock_time_get(
&self,
&mut self,
id: types::Clockid,
precision: types::Timestamp,
) -> Result<types::Timestamp, Error> {
@@ -374,7 +374,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn fd_advise(
&self,
&mut self,
fd: types::Fd,
offset: types::Filesize,
len: types::Filesize,
@@ -384,7 +384,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn fd_allocate(
&self,
&mut self,
fd: types::Fd,
offset: types::Filesize,
len: types::Filesize,
@@ -392,24 +392,28 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Snapshot1::fd_allocate(self, fd.into(), offset, len).await
}
async fn fd_close(&self, fd: types::Fd) -> Result<(), Error> {
async fn fd_close(&mut self, fd: types::Fd) -> Result<(), Error> {
Snapshot1::fd_close(self, fd.into()).await
}
async fn fd_datasync(&self, fd: types::Fd) -> Result<(), Error> {
async fn fd_datasync(&mut self, fd: types::Fd) -> Result<(), Error> {
Snapshot1::fd_datasync(self, fd.into()).await
}
async fn fd_fdstat_get(&self, fd: types::Fd) -> Result<types::Fdstat, Error> {
async fn fd_fdstat_get(&mut self, fd: types::Fd) -> Result<types::Fdstat, Error> {
Ok(Snapshot1::fd_fdstat_get(self, fd.into()).await?.into())
}
async fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> {
async fn fd_fdstat_set_flags(
&mut self,
fd: types::Fd,
flags: types::Fdflags,
) -> Result<(), Error> {
Snapshot1::fd_fdstat_set_flags(self, fd.into(), flags.into()).await
}
async fn fd_fdstat_set_rights(
&self,
&mut self,
fd: types::Fd,
fs_rights_base: types::Rights,
fs_rights_inheriting: types::Rights,
@@ -423,12 +427,12 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
.await
}
async fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
async fn fd_filestat_get(&mut self, fd: types::Fd) -> Result<types::Filestat, Error> {
Ok(Snapshot1::fd_filestat_get(self, fd.into()).await?.into())
}
async fn fd_filestat_set_size(
&self,
&mut self,
fd: types::Fd,
size: types::Filesize,
) -> Result<(), Error> {
@@ -436,7 +440,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn fd_filestat_set_times(
&self,
&mut self,
fd: types::Fd,
atim: types::Timestamp,
mtim: types::Timestamp,
@@ -454,7 +458,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
// representation to a std::io::IoSlice(Mut) representation.
async fn fd_read<'a>(
&self,
&mut self,
fd: types::Fd,
iovs: &types::IovecArray<'a>,
) -> Result<types::Size, Error> {
@@ -480,7 +484,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn fd_pread<'a>(
&self,
&mut self,
fd: types::Fd,
iovs: &types::IovecArray<'a>,
offset: types::Filesize,
@@ -509,7 +513,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn fd_write<'a>(
&self,
&mut self,
fd: types::Fd,
ciovs: &types::CiovecArray<'a>,
) -> Result<types::Size, Error> {
@@ -535,7 +539,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn fd_pwrite<'a>(
&self,
&mut self,
fd: types::Fd,
ciovs: &types::CiovecArray<'a>,
offset: types::Filesize,
@@ -563,12 +567,12 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Ok(types::Size::try_from(bytes_written)?)
}
async fn fd_prestat_get(&self, fd: types::Fd) -> Result<types::Prestat, Error> {
async fn fd_prestat_get(&mut self, fd: types::Fd) -> Result<types::Prestat, Error> {
Ok(Snapshot1::fd_prestat_get(self, fd.into()).await?.into())
}
async fn fd_prestat_dir_name<'a>(
&self,
&mut self,
fd: types::Fd,
path: &GuestPtr<'a, u8>,
path_max_len: types::Size,
@@ -576,12 +580,12 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Snapshot1::fd_prestat_dir_name(self, fd.into(), path, path_max_len).await
}
async fn fd_renumber(&self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
async fn fd_renumber(&mut self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
Snapshot1::fd_renumber(self, from.into(), to.into()).await
}
async fn fd_seek(
&self,
&mut self,
fd: types::Fd,
offset: types::Filedelta,
whence: types::Whence,
@@ -589,16 +593,16 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Snapshot1::fd_seek(self, fd.into(), offset, whence.into()).await
}
async fn fd_sync(&self, fd: types::Fd) -> Result<(), Error> {
async fn fd_sync(&mut self, fd: types::Fd) -> Result<(), Error> {
Snapshot1::fd_sync(self, fd.into()).await
}
async fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize, Error> {
async fn fd_tell(&mut self, fd: types::Fd) -> Result<types::Filesize, Error> {
Snapshot1::fd_tell(self, fd.into()).await
}
async fn fd_readdir<'a>(
&self,
&mut self,
fd: types::Fd,
buf: &GuestPtr<'a, u8>,
buf_len: types::Size,
@@ -608,7 +612,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_create_directory<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
) -> Result<(), Error> {
@@ -616,7 +620,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_filestat_get<'a>(
&self,
&mut self,
dirfd: types::Fd,
flags: types::Lookupflags,
path: &GuestPtr<'a, str>,
@@ -629,7 +633,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_filestat_set_times<'a>(
&self,
&mut self,
dirfd: types::Fd,
flags: types::Lookupflags,
path: &GuestPtr<'a, str>,
@@ -650,7 +654,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_link<'a>(
&self,
&mut self,
src_fd: types::Fd,
src_flags: types::Lookupflags,
src_path: &GuestPtr<'a, str>,
@@ -669,7 +673,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_open<'a>(
&self,
&mut self,
dirfd: types::Fd,
dirflags: types::Lookupflags,
path: &GuestPtr<'a, str>,
@@ -693,7 +697,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_readlink<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
buf: &GuestPtr<'a, u8>,
@@ -703,7 +707,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_remove_directory<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
) -> Result<(), Error> {
@@ -711,7 +715,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_rename<'a>(
&self,
&mut self,
src_fd: types::Fd,
src_path: &GuestPtr<'a, str>,
dest_fd: types::Fd,
@@ -721,7 +725,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_symlink<'a>(
&self,
&mut self,
src_path: &GuestPtr<'a, str>,
dirfd: types::Fd,
dest_path: &GuestPtr<'a, str>,
@@ -730,7 +734,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn path_unlink_file<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
) -> Result<(), Error> {
@@ -745,7 +749,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
// The bodies of these functions is mostly about converting the GuestPtr and types::-based
// representation to use the Poll abstraction.
async fn poll_oneoff<'a>(
&self,
&mut self,
subs: &GuestPtr<'a, types::Subscription>,
events: &GuestPtr<'a, types::Event>,
nsubscriptions: types::Size,
@@ -779,11 +783,11 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
}
let table = self.table();
let table = &mut self.table;
let mut sub_fds: HashSet<types::Fd> = HashSet::new();
// We need these refmuts to outlive Poll, which will hold the &mut dyn WasiFile inside
let mut read_refs: Vec<(RefMut<'_, dyn WasiFile>, Userdata)> = Vec::new();
let mut write_refs: Vec<(RefMut<'_, dyn WasiFile>, Userdata)> = Vec::new();
let mut reads: Vec<(u32, Userdata)> = Vec::new();
let mut writes: Vec<(u32, Userdata)> = Vec::new();
let mut poll = Poll::new();
let subs = subs.as_array(nsubscriptions);
@@ -828,10 +832,10 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
} else {
sub_fds.insert(fd);
}
let file_ref = table
table
.get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?;
read_refs.push((file_ref, sub.userdata.into()));
.get_cap_mut(FileCaps::POLL_READWRITE)?;
reads.push((u32::from(fd), sub.userdata.into()));
}
types::SubscriptionU::FdWrite(writesub) => {
let fd = writesub.file_descriptor;
@@ -841,10 +845,10 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
} else {
sub_fds.insert(fd);
}
let file_ref = table
table
.get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?;
write_refs.push((file_ref, sub.userdata.into()));
.get_cap_mut(FileCaps::POLL_READWRITE)?;
writes.push((u32::from(fd), sub.userdata.into()));
}
}
}
@@ -924,20 +928,20 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Ok(num_results.try_into().expect("results fit into memory"))
}
async fn proc_exit(&self, status: types::Exitcode) -> wiggle::Trap {
async fn proc_exit(&mut self, status: types::Exitcode) -> wiggle::Trap {
Snapshot1::proc_exit(self, status).await
}
async fn proc_raise(&self, _sig: types::Signal) -> Result<(), Error> {
async fn proc_raise(&mut self, _sig: types::Signal) -> Result<(), Error> {
Err(Error::trap("proc_raise unsupported"))
}
async fn sched_yield(&self) -> Result<(), Error> {
async fn sched_yield(&mut self) -> Result<(), Error> {
Snapshot1::sched_yield(self).await
}
async fn random_get<'a>(
&self,
&mut self,
buf: &GuestPtr<'a, u8>,
buf_len: types::Size,
) -> Result<(), Error> {
@@ -945,7 +949,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn sock_recv<'a>(
&self,
&mut self,
_fd: types::Fd,
_ri_data: &types::IovecArray<'a>,
_ri_flags: types::Riflags,
@@ -954,7 +958,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
async fn sock_send<'a>(
&self,
&mut self,
_fd: types::Fd,
_si_data: &types::CiovecArray<'a>,
_si_flags: types::Siflags,
@@ -962,7 +966,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Err(Error::trap("sock_send unsupported"))
}
async fn sock_shutdown(&self, _fd: types::Fd, _how: types::Sdflags) -> Result<(), Error> {
async fn sock_shutdown(&mut self, _fd: types::Fd, _how: types::Sdflags) -> Result<(), Error> {
Err(Error::trap("sock_shutdown unsupported"))
}
}

View File

@@ -1,8 +1,8 @@
use crate::{
dir::{DirCaps, DirEntry, DirEntryExt, DirFdStat, ReaddirCursor, ReaddirEntity, TableDirExt},
file::{
Advice, FdFlags, FdStat, FileCaps, FileEntry, FileEntryExt, FileEntryMutExt, FileType,
Filestat, OFlags, TableFileExt, WasiFile,
Advice, FdFlags, FdStat, FileCaps, FileEntry, FileEntryExt, FileType, Filestat, OFlags,
TableFileExt, WasiFile,
},
sched::{
subscription::{RwEventFlags, SubscriptionResult},
@@ -12,7 +12,6 @@ use crate::{
};
use anyhow::Context;
use cap_std::time::{Duration, SystemClock};
use std::cell::{Ref, RefMut};
use std::collections::HashSet;
use std::convert::{TryFrom, TryInto};
use std::io::{IoSlice, IoSliceMut};
@@ -26,7 +25,8 @@ wiggle::from_witx!({
// 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: *
async: *,
wasmtime: false
});
impl wiggle::GuestErrorType for types::Errno {
@@ -36,7 +36,7 @@ impl wiggle::GuestErrorType for types::Errno {
}
impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&self, e: Error) -> Result<types::Errno, wiggle::Trap> {
fn errno_from_error(&mut self, e: Error) -> Result<types::Errno, wiggle::Trap> {
debug!("Error: {:?}", e);
e.try_into()
.map_err(|e| wiggle::Trap::String(format!("{:?}", e)))
@@ -196,30 +196,30 @@ impl TryFrom<std::io::Error> for types::Errno {
#[wiggle::async_trait]
impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
async fn args_get<'b>(
&self,
&mut self,
argv: &GuestPtr<'b, GuestPtr<'b, u8>>,
argv_buf: &GuestPtr<'b, u8>,
) -> Result<(), Error> {
self.args.write_to_guest(argv_buf, argv)
}
async fn args_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
async fn args_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
Ok((self.args.number_elements(), self.args.cumulative_size()))
}
async fn environ_get<'b>(
&self,
&mut self,
environ: &GuestPtr<'b, GuestPtr<'b, u8>>,
environ_buf: &GuestPtr<'b, u8>,
) -> Result<(), Error> {
self.env.write_to_guest(environ_buf, environ)
}
async fn environ_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
async fn environ_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
Ok((self.env.number_elements(), self.env.cumulative_size()))
}
async fn clock_res_get(&self, id: types::Clockid) -> Result<types::Timestamp, Error> {
async fn clock_res_get(&mut self, id: types::Clockid) -> Result<types::Timestamp, Error> {
let resolution = match id {
types::Clockid::Realtime => Ok(self.clocks.system.resolution()),
types::Clockid::Monotonic => Ok(self.clocks.monotonic.resolution()),
@@ -231,7 +231,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn clock_time_get(
&self,
&mut self,
id: types::Clockid,
precision: types::Timestamp,
) -> Result<types::Timestamp, Error> {
@@ -256,7 +256,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_advise(
&self,
&mut self,
fd: types::Fd,
offset: types::Filesize,
len: types::Filesize,
@@ -271,7 +271,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_allocate(
&self,
&mut self,
fd: types::Fd,
offset: types::Filesize,
len: types::Filesize,
@@ -284,8 +284,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(())
}
async fn fd_close(&self, fd: types::Fd) -> Result<(), Error> {
let mut table = self.table();
async fn fd_close(&mut self, fd: types::Fd) -> Result<(), Error> {
let table = self.table();
let fd = u32::from(fd);
// Fail fast: If not present in table, Badf
@@ -297,7 +297,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let _ = table.delete(fd);
} else if table.is::<DirEntry>(fd) {
// We cannot close preopened directories
let dir_entry: Ref<DirEntry> = table.get(fd).unwrap();
let dir_entry: &DirEntry = table.get(fd).unwrap();
if dir_entry.preopen_path().is_some() {
return Err(Error::not_supported().context("cannot close propened directory"));
}
@@ -310,7 +310,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(())
}
async fn fd_datasync(&self, fd: types::Fd) -> Result<(), Error> {
async fn fd_datasync(&mut self, fd: types::Fd) -> Result<(), Error> {
self.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::DATASYNC)?
@@ -319,15 +319,15 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(())
}
async fn fd_fdstat_get(&self, fd: types::Fd) -> Result<types::Fdstat, Error> {
async fn fd_fdstat_get(&mut self, fd: types::Fd) -> Result<types::Fdstat, Error> {
let table = self.table();
let fd = u32::from(fd);
if table.is::<FileEntry>(fd) {
let file_entry: Ref<FileEntry> = table.get(fd)?;
let file_entry: &FileEntry = table.get(fd)?;
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)?;
let dir_entry: &DirEntry = table.get(fd)?;
let dir_fdstat = dir_entry.get_dir_fdstat();
Ok(types::Fdstat::from(&dir_fdstat))
} else {
@@ -335,16 +335,20 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
}
async fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> {
async fn fd_fdstat_set_flags(
&mut self,
fd: types::Fd,
flags: types::Fdflags,
) -> Result<(), Error> {
self.table()
.get_file_mut(u32::from(fd))?
.get_cap(FileCaps::FDSTAT_SET_FLAGS)?
.get_cap_mut(FileCaps::FDSTAT_SET_FLAGS)?
.set_fdflags(FdFlags::from(flags))
.await
}
async fn fd_fdstat_set_rights(
&self,
&mut self,
fd: types::Fd,
fs_rights_base: types::Rights,
fs_rights_inheriting: types::Rights,
@@ -352,11 +356,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let table = self.table();
let fd = u32::from(fd);
if table.is::<FileEntry>(fd) {
let mut file_entry: RefMut<FileEntry> = table.get_mut(fd)?;
let file_entry: &mut FileEntry = table.get_mut(fd)?;
let file_caps = FileCaps::from(&fs_rights_base);
file_entry.drop_caps_to(file_caps)
} else if table.is::<DirEntry>(fd) {
let mut dir_entry: RefMut<DirEntry> = table.get_mut(fd)?;
let dir_entry: &mut DirEntry = table.get_mut(fd)?;
let dir_caps = DirCaps::from(&fs_rights_base);
let file_caps = FileCaps::from(&fs_rights_inheriting);
dir_entry.drop_caps_to(dir_caps, file_caps)
@@ -365,7 +369,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
}
async fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
async fn fd_filestat_get(&mut self, fd: types::Fd) -> Result<types::Filestat, Error> {
let table = self.table();
let fd = u32::from(fd);
if table.is::<FileEntry>(fd) {
@@ -388,7 +392,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_filestat_set_size(
&self,
&mut self,
fd: types::Fd,
size: types::Filesize,
) -> Result<(), Error> {
@@ -401,7 +405,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_filestat_set_times(
&self,
&mut self,
fd: types::Fd,
atim: types::Timestamp,
mtim: types::Timestamp,
@@ -438,7 +442,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_read<'a>(
&self,
&mut self,
fd: types::Fd,
iovs: &types::IovecArray<'a>,
) -> Result<types::Size, Error> {
@@ -464,7 +468,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_pread<'a>(
&self,
&mut self,
fd: types::Fd,
iovs: &types::IovecArray<'a>,
offset: types::Filesize,
@@ -493,7 +497,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_write<'a>(
&self,
&mut self,
fd: types::Fd,
ciovs: &types::CiovecArray<'a>,
) -> Result<types::Size, Error> {
@@ -519,7 +523,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_pwrite<'a>(
&self,
&mut self,
fd: types::Fd,
ciovs: &types::CiovecArray<'a>,
offset: types::Filesize,
@@ -547,9 +551,9 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(types::Size::try_from(bytes_written)?)
}
async fn fd_prestat_get(&self, fd: types::Fd) -> Result<types::Prestat, Error> {
async fn fd_prestat_get(&mut self, fd: types::Fd) -> Result<types::Prestat, Error> {
let table = self.table();
let dir_entry: Ref<DirEntry> = table.get(u32::from(fd)).map_err(|_| Error::badf())?;
let dir_entry: &DirEntry = table.get(u32::from(fd)).map_err(|_| Error::badf())?;
if let Some(ref preopen) = dir_entry.preopen_path() {
let path_str = preopen.to_str().ok_or_else(|| Error::not_supported())?;
let pr_name_len = u32::try_from(path_str.as_bytes().len())?;
@@ -560,13 +564,13 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_prestat_dir_name<'a>(
&self,
&mut self,
fd: types::Fd,
path: &GuestPtr<'a, u8>,
path_max_len: types::Size,
) -> Result<(), Error> {
let table = self.table();
let dir_entry: Ref<DirEntry> = table.get(u32::from(fd)).map_err(|_| Error::not_dir())?;
let dir_entry: &DirEntry = table.get(u32::from(fd)).map_err(|_| Error::not_dir())?;
if let Some(ref preopen) = dir_entry.preopen_path() {
let path_bytes = preopen
.to_str()
@@ -583,8 +587,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Err(Error::not_supported())
}
}
async fn fd_renumber(&self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
let mut table = self.table();
async fn fd_renumber(&mut self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
let table = self.table();
let from = u32::from(from);
let to = u32::from(to);
if !table.contains_key(from) {
@@ -601,7 +605,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_seek(
&self,
&mut self,
fd: types::Fd,
offset: types::Filedelta,
whence: types::Whence,
@@ -628,7 +632,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(newoffset)
}
async fn fd_sync(&self, fd: types::Fd) -> Result<(), Error> {
async fn fd_sync(&mut self, fd: types::Fd) -> Result<(), Error> {
self.table()
.get_file(u32::from(fd))?
.get_cap(FileCaps::SYNC)?
@@ -637,7 +641,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(())
}
async fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize, Error> {
async fn fd_tell(&mut self, fd: types::Fd) -> Result<types::Filesize, Error> {
// XXX should this be stream_position?
let offset = self
.table()
@@ -649,7 +653,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn fd_readdir<'a>(
&self,
&mut self,
fd: types::Fd,
buf: &GuestPtr<'a, u8>,
buf_len: types::Size,
@@ -703,7 +707,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_create_directory<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
) -> Result<(), Error> {
@@ -715,7 +719,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_filestat_get<'a>(
&self,
&mut self,
dirfd: types::Fd,
flags: types::Lookupflags,
path: &GuestPtr<'a, str>,
@@ -733,7 +737,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_filestat_set_times<'a>(
&self,
&mut self,
dirfd: types::Fd,
flags: types::Lookupflags,
path: &GuestPtr<'a, str>,
@@ -761,7 +765,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_link<'a>(
&self,
&mut self,
src_fd: types::Fd,
src_flags: types::Lookupflags,
src_path: &GuestPtr<'a, str>,
@@ -791,7 +795,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_open<'a>(
&self,
&mut self,
dirfd: types::Fd,
dirflags: types::Lookupflags,
path: &GuestPtr<'a, str>,
@@ -800,7 +804,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fs_rights_inheriting: types::Rights,
fdflags: types::Fdflags,
) -> Result<types::Fd, Error> {
let mut table = self.table();
let table = self.table();
let dirfd = u32::from(dirfd);
if table.is::<FileEntry>(dirfd) {
return Err(Error::not_dir());
@@ -850,7 +854,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_readlink<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
buf: &GuestPtr<'a, u8>,
@@ -876,7 +880,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_remove_directory<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
) -> Result<(), Error> {
@@ -888,7 +892,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_rename<'a>(
&self,
&mut self,
src_fd: types::Fd,
src_path: &GuestPtr<'a, str>,
dest_fd: types::Fd,
@@ -911,7 +915,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_symlink<'a>(
&self,
&mut self,
src_path: &GuestPtr<'a, str>,
dirfd: types::Fd,
dest_path: &GuestPtr<'a, str>,
@@ -924,7 +928,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn path_unlink_file<'a>(
&self,
&mut self,
dirfd: types::Fd,
path: &GuestPtr<'a, str>,
) -> Result<(), Error> {
@@ -936,7 +940,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn poll_oneoff<'a>(
&self,
&mut self,
subs: &GuestPtr<'a, types::Subscription>,
events: &GuestPtr<'a, types::Event>,
nsubscriptions: types::Size,
@@ -970,11 +974,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
}
let table = self.table();
let table = &mut self.table;
let mut sub_fds: HashSet<types::Fd> = HashSet::new();
// We need these refmuts to outlive Poll, which will hold the &mut dyn WasiFile inside
let mut read_refs: Vec<(RefMut<'_, dyn WasiFile>, Userdata)> = Vec::new();
let mut write_refs: Vec<(RefMut<'_, dyn WasiFile>, Userdata)> = Vec::new();
let mut read_refs: Vec<(&dyn WasiFile, Userdata)> = Vec::new();
let mut write_refs: Vec<(&dyn WasiFile, Userdata)> = Vec::new();
let mut poll = Poll::new();
let subs = subs.as_array(nsubscriptions);
@@ -1020,7 +1024,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
sub_fds.insert(fd);
}
let file_ref = table
.get_file_mut(u32::from(fd))?
.get_file(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?;
read_refs.push((file_ref, sub.userdata.into()));
}
@@ -1033,7 +1037,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
sub_fds.insert(fd);
}
let file_ref = table
.get_file_mut(u32::from(fd))?
.get_file(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?;
write_refs.push((file_ref, sub.userdata.into()));
}
@@ -1041,10 +1045,10 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
for (f, ud) in read_refs.iter_mut() {
poll.subscribe_read(f.deref_mut(), *ud);
poll.subscribe_read(*f, *ud);
}
for (f, ud) in write_refs.iter_mut() {
poll.subscribe_write(f.deref_mut(), *ud);
poll.subscribe_write(*f, *ud);
}
self.sched.poll_oneoff(&mut poll).await?;
@@ -1122,7 +1126,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(num_results.try_into().expect("results fit into memory"))
}
async fn proc_exit(&self, status: types::Exitcode) -> wiggle::Trap {
async fn proc_exit(&mut self, status: types::Exitcode) -> wiggle::Trap {
// Check that the status is within WASI's range.
if status < 126 {
wiggle::Trap::I32Exit(status as i32)
@@ -1131,26 +1135,26 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
}
async fn proc_raise(&self, _sig: types::Signal) -> Result<(), Error> {
async fn proc_raise(&mut self, _sig: types::Signal) -> Result<(), Error> {
Err(Error::trap("proc_raise unsupported"))
}
async fn sched_yield(&self) -> Result<(), Error> {
async fn sched_yield(&mut self) -> Result<(), Error> {
self.sched.sched_yield().await
}
async fn random_get<'a>(
&self,
&mut self,
buf: &GuestPtr<'a, u8>,
buf_len: types::Size,
) -> Result<(), Error> {
let mut buf = buf.as_array(buf_len).as_slice_mut()?;
self.random.borrow_mut().try_fill_bytes(buf.deref_mut())?;
self.random.try_fill_bytes(buf.deref_mut())?;
Ok(())
}
async fn sock_recv<'a>(
&self,
&mut self,
_fd: types::Fd,
_ri_data: &types::IovecArray<'a>,
_ri_flags: types::Riflags,
@@ -1159,7 +1163,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}
async fn sock_send<'a>(
&self,
&mut self,
_fd: types::Fd,
_si_data: &types::CiovecArray<'a>,
_si_flags: types::Siflags,
@@ -1167,7 +1171,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Err(Error::trap("sock_send unsupported"))
}
async fn sock_shutdown(&self, _fd: types::Fd, _how: types::Sdflags) -> Result<(), Error> {
async fn sock_shutdown(&mut self, _fd: types::Fd, _how: types::Sdflags) -> Result<(), Error> {
Err(Error::trap("sock_shutdown unsupported"))
}
}

View File

@@ -1,6 +1,5 @@
use crate::{Error, ErrorExt};
use std::any::Any;
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
/// The `Table` type is designed to map u32 handles to resources. The table is now part of the
@@ -11,7 +10,7 @@ use std::collections::HashMap;
/// The `Table` type is intended to model how the Interface Types concept of Resources is shaping
/// up. Right now it is just an approximation.
pub struct Table {
map: HashMap<u32, RefCell<Box<dyn Any>>>,
map: HashMap<u32, Box<dyn Any + Send + Sync>>,
next_key: u32,
}
@@ -25,12 +24,12 @@ impl Table {
}
/// Insert a resource at a certain index.
pub fn insert_at(&mut self, key: u32, a: Box<dyn Any>) {
self.map.insert(key, RefCell::new(a));
pub fn insert_at(&mut self, key: u32, a: Box<dyn Any + Send + Sync>) {
self.map.insert(key, a);
}
/// Insert a resource at the next available index.
pub fn push(&mut self, a: Box<dyn Any>) -> Result<u32, Error> {
pub fn push(&mut self, a: Box<dyn Any + Send + Sync>) -> Result<u32, Error> {
// NOTE: The performance of this new key calculation could be very bad once keys wrap
// around.
if self.map.len() == u32::MAX as usize {
@@ -42,7 +41,7 @@ impl Table {
if self.map.contains_key(&key) {
continue;
}
self.map.insert(key, RefCell::new(a));
self.map.insert(key, a);
return Ok(key);
}
}
@@ -55,12 +54,8 @@ impl Table {
/// Check if the resource at a given index can be downcast to a given type.
/// Note: this will always fail if the resource is already borrowed.
pub fn is<T: Any + Sized>(&self, key: u32) -> bool {
if let Some(refcell) = self.map.get(&key) {
if let Ok(refmut) = refcell.try_borrow_mut() {
refmut.is::<T>()
} else {
false
}
if let Some(r) = self.map.get(&key) {
r.is::<T>()
} else {
false
}
@@ -69,17 +64,10 @@ impl Table {
/// Get an immutable reference to a resource of a given type at a given index. Multiple
/// immutable references can be borrowed at any given time. Borrow failure
/// results in a trapping error.
pub fn get<T: Any + Sized>(&self, key: u32) -> Result<Ref<T>, Error> {
if let Some(refcell) = self.map.get(&key) {
if let Ok(r) = refcell.try_borrow() {
if r.is::<T>() {
Ok(Ref::map(r, |r| r.downcast_ref::<T>().unwrap()))
} else {
Err(Error::badf().context("element is a different type"))
}
} else {
Err(Error::trap("table get of mutably borrowed element"))
}
pub fn get<T: Any + Sized>(&self, key: u32) -> Result<&T, Error> {
if let Some(r) = self.map.get(&key) {
r.downcast_ref::<T>()
.ok_or_else(|| Error::badf().context("element is a different type"))
} else {
Err(Error::badf().context("key not in table"))
}
@@ -87,17 +75,10 @@ impl Table {
/// Get a mutable reference to a resource of a given type at a given index. Only one mutable
/// reference can be borrowed at any given time. Borrow failure results in a trapping error.
pub fn get_mut<T: Any + Sized>(&self, key: u32) -> Result<RefMut<T>, Error> {
if let Some(refcell) = self.map.get(&key) {
if let Ok(r) = refcell.try_borrow_mut() {
if r.is::<T>() {
Ok(RefMut::map(r, |r| r.downcast_mut::<T>().unwrap()))
} else {
Err(Error::badf().context("element is a different type"))
}
} else {
Err(Error::trap("table get_mut of borrowed element"))
}
pub fn get_mut<T: Any + Sized>(&mut self, key: u32) -> Result<&mut T, Error> {
if let Some(r) = self.map.get_mut(&key) {
r.downcast_mut::<T>()
.ok_or_else(|| Error::badf().context("element is a different type"))
} else {
Err(Error::badf().context("key not in table"))
}
@@ -105,7 +86,7 @@ impl Table {
/// Remove a resource at a given index from the table. Returns the resource
/// if it was present.
pub fn delete(&mut self, key: u32) -> Option<Box<dyn Any>> {
self.map.remove(&key).map(|rc| RefCell::into_inner(rc))
pub fn delete(&mut self, key: u32) -> Option<Box<dyn Any + Send + Sync>> {
self.map.remove(&key)
}
}