Skip to content

Commit

Permalink
see what this looks like without Handle or HandleMut
Browse files Browse the repository at this point in the history
  • Loading branch information
iximeow committed Feb 20, 2020
1 parent 728ec70 commit 0c571c6
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 140 deletions.
100 changes: 16 additions & 84 deletions crates/wasi-common/src/fdentry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,6 @@ use std::ops::{Deref, DerefMut};
use std::path::PathBuf;
use std::{fmt, fs, io};

pub(crate) enum HandleMut<'handle> {
OsHandle(&'handle mut OsHandle),
VirtualFile(&'handle mut dyn VirtualFile),
Stream(OsHandleRef<'handle>),
}

impl<'descriptor> fmt::Debug for HandleMut<'descriptor> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
HandleMut::OsHandle(file) => {
// coerce to the target debug-printable type
let file: &fs::File = file;
write!(f, "{:?}", file)
}
HandleMut::Stream(stream) => {
// coerce to the target debug-printable type
let file: &fs::File = stream;
write!(f, "{:?}", file)
}
HandleMut::VirtualFile(_) => write!(f, "VirtualFile"),
}
}
}

pub(crate) enum Handle<'handle> {
OsHandle(&'handle OsHandle),
VirtualFile(&'handle dyn VirtualFile),
Stream(OsHandleRef<'handle>),
}

impl<'descriptor> Handle<'descriptor> {
pub(crate) fn try_clone(&self) -> io::Result<Descriptor> {
match self {
Handle::OsHandle(file) => file.try_clone().map(|f| OsHandle::from(f).into()),
Handle::Stream(stream) => stream.try_clone().map(|f| OsHandle::from(f).into()),
Handle::VirtualFile(virt) => virt.try_clone().map(Descriptor::VirtualFile),
}
}
}

impl<'descriptor> fmt::Debug for Handle<'descriptor> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Handle::OsHandle(file) => {
// coerce to the target debug-printable type
let file: &fs::File = file;
write!(f, "{:?}", file)
}
Handle::Stream(stream) => {
// coerce to the target debug-printable type
let file: &fs::File = stream;
write!(f, "{:?}", file)
}
Handle::VirtualFile(_) => write!(f, "VirtualFile"),
}
}
}

pub(crate) enum Descriptor {
OsHandle(OsHandle),
VirtualFile(Box<dyn VirtualFile>),
Expand Down Expand Up @@ -101,48 +43,38 @@ impl fmt::Debug for Descriptor {
}

impl Descriptor {
pub(crate) fn try_clone(&self) -> io::Result<Descriptor> {
match self {
Descriptor::OsHandle(file) => file.try_clone().map(|f| OsHandle::from(f).into()),
Descriptor::VirtualFile(virt) => virt.try_clone().map(Descriptor::VirtualFile),
Descriptor::Stdin => Ok(Descriptor::Stdin),
Descriptor::Stdout => Ok(Descriptor::Stdout),
Descriptor::Stderr => Ok(Descriptor::Stderr),
}
}

/// Return a reference to the `OsHandle` or `VirtualFile` treating it as an
/// actual file/dir, and allowing operations which require an actual file and
/// not just a stream or socket file descriptor.
pub(crate) fn as_file<'descriptor>(&'descriptor self) -> Result<Handle<'descriptor>> {
pub(crate) fn as_file<'descriptor>(&'descriptor self) -> Result<&'descriptor Descriptor> {
match self {
Self::OsHandle(handle) => Ok(Handle::OsHandle(handle)),
Self::VirtualFile(virt) => Ok(Handle::VirtualFile(virt.as_ref())),
Self::OsHandle(_) => Ok(self),
Self::VirtualFile(_) => Ok(self),
_ => Err(Error::EBADF),
}
}

/// Like `as_file`, but return a mutable reference.
pub(crate) fn as_file_mut<'descriptor>(
&'descriptor mut self,
) -> Result<HandleMut<'descriptor>> {
) -> Result<&'descriptor mut Descriptor> {
match self {
Self::OsHandle(handle) => Ok(HandleMut::OsHandle(handle)),
Self::VirtualFile(virt) => Ok(HandleMut::VirtualFile(virt.as_mut())),
Self::OsHandle(_) => Ok(self),
Self::VirtualFile(_) => Ok(self),
_ => Err(Error::EBADF),
}
}

pub(crate) fn as_handle<'descriptor>(&'descriptor self) -> Handle<'descriptor> {
match self {
Self::VirtualFile(virt) => Handle::VirtualFile(virt.as_ref()),
Self::OsHandle(handle) => Handle::OsHandle(handle),
other @ Self::Stdin | other @ Self::Stderr | other @ Self::Stdout => {
Handle::Stream(other.as_os_handle())
}
}
}

pub(crate) fn as_handle_mut<'descriptor>(&'descriptor mut self) -> HandleMut<'descriptor> {
match self {
Self::VirtualFile(virt) => HandleMut::VirtualFile(virt.as_mut()),
Self::OsHandle(handle) => HandleMut::OsHandle(handle),
other @ Self::Stdin | other @ Self::Stderr | other @ Self::Stdout => {
HandleMut::Stream(other.as_os_handle())
}
}
}

/// Return an `OsHandle`, which may be a stream or socket file descriptor.
pub(crate) fn as_os_handle<'descriptor>(&'descriptor self) -> OsHandleRef<'descriptor> {
descriptor_as_oshandle(self)
Expand Down
110 changes: 55 additions & 55 deletions crates/wasi-common/src/hostcalls_impl/fs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
use super::fs_helpers::path_get;
use crate::ctx::WasiCtx;
use crate::fdentry::{Descriptor, FdEntry, Handle, HandleMut};
use crate::fdentry::{Descriptor, FdEntry};
use crate::helpers::*;
use crate::host::Dirent;
use crate::memory::*;
Expand Down Expand Up @@ -42,13 +42,12 @@ pub(crate) unsafe fn fd_datasync(

let file = wasi_ctx
.get_fd_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_DATASYNC, 0)?
.as_handle();
.as_descriptor(wasi::__WASI_RIGHTS_FD_DATASYNC, 0)?;

match file {
Handle::OsHandle(fd) => fd.sync_data().map_err(Into::into),
Handle::Stream(stream) => stream.sync_data().map_err(Into::into),
Handle::VirtualFile(virt) => virt.datasync(),
Descriptor::OsHandle(fd) => fd.sync_data().map_err(Into::into),
Descriptor::VirtualFile(virt) => virt.datasync(),
other => other.as_os_handle().sync_data().map_err(Into::into),
}
}

Expand Down Expand Up @@ -83,9 +82,9 @@ pub(crate) unsafe fn fd_pread(
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
let mut buf = vec![0; buf_size];
let host_nread = match file {
Handle::OsHandle(fd) => hostcalls_impl::fd_pread(&fd, &mut buf, offset)?,
Handle::VirtualFile(virt) => virt.pread(&mut buf, offset)?,
Handle::Stream(_) => {
Descriptor::OsHandle(fd) => hostcalls_impl::fd_pread(&fd, &mut buf, offset)?,
Descriptor::VirtualFile(virt) => virt.pread(&mut buf, offset)?,
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand Down Expand Up @@ -149,9 +148,9 @@ pub(crate) unsafe fn fd_pwrite(
));
}
let host_nwritten = match file {
Handle::OsHandle(fd) => hostcalls_impl::fd_pwrite(&fd, &buf, offset)?,
Handle::VirtualFile(virt) => virt.pwrite(buf.as_mut(), offset)?,
Handle::Stream(_) => {
Descriptor::OsHandle(fd) => hostcalls_impl::fd_pwrite(&fd, &buf, offset)?,
Descriptor::VirtualFile(virt) => virt.pwrite(buf.as_mut(), offset)?,
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand Down Expand Up @@ -266,9 +265,9 @@ pub(crate) unsafe fn fd_seek(
_ => return Err(Error::EINVAL),
};
let host_newoffset = match file {
HandleMut::OsHandle(fd) => fd.seek(pos)?,
HandleMut::VirtualFile(virt) => virt.seek(pos)?,
HandleMut::Stream(_) => {
Descriptor::OsHandle(fd) => fd.seek(pos)?,
Descriptor::VirtualFile(virt) => virt.seek(pos)?,
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand All @@ -294,9 +293,9 @@ pub(crate) unsafe fn fd_tell(
.as_file_mut()?;

let host_offset = match file {
HandleMut::OsHandle(fd) => fd.seek(SeekFrom::Current(0))?,
HandleMut::VirtualFile(virt) => virt.seek(SeekFrom::Current(0))?,
HandleMut::Stream(_) => {
Descriptor::OsHandle(fd) => fd.seek(SeekFrom::Current(0))?,
Descriptor::VirtualFile(virt) => virt.seek(SeekFrom::Current(0))?,
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand All @@ -317,12 +316,12 @@ pub(crate) unsafe fn fd_fdstat_get(
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);

let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
let wasi_file = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_handle();
let wasi_file = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?;

let fs_flags = match wasi_file {
Handle::OsHandle(wasi_fd) => hostcalls_impl::fd_fdstat_get(&wasi_fd)?,
Handle::Stream(stream) => hostcalls_impl::fd_fdstat_get(&stream)?,
Handle::VirtualFile(virt) => virt.fdstat_get(),
Descriptor::OsHandle(wasi_fd) => hostcalls_impl::fd_fdstat_get(&wasi_fd)?,
Descriptor::VirtualFile(virt) => virt.fdstat_get(),
other => hostcalls_impl::fd_fdstat_get(&other.as_os_handle())?,
};

let fe = wasi_ctx.get_fd_entry(fd)?;
Expand All @@ -348,26 +347,27 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
.get_fd_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)?;

match descriptor.as_handle_mut() {
HandleMut::OsHandle(handle) => {
match descriptor {
Descriptor::OsHandle(handle) => {
let set_result =
hostcalls_impl::fd_fdstat_set_flags(&handle, fdflags)?.map(Descriptor::OsHandle);

if let Some(new_descriptor) = set_result {
*descriptor = new_descriptor;
}
}
HandleMut::Stream(handle) => {
Descriptor::VirtualFile(handle) => {
handle.fdstat_set_flags(fdflags)?;
}
_ => {
let set_result =
hostcalls_impl::fd_fdstat_set_flags(&handle, fdflags)?.map(Descriptor::OsHandle);
hostcalls_impl::fd_fdstat_set_flags(&descriptor.as_os_handle(), fdflags)?
.map(Descriptor::OsHandle);

if let Some(new_descriptor) = set_result {
*descriptor = new_descriptor;
}
}
HandleMut::VirtualFile(handle) => {
handle.fdstat_set_flags(fdflags)?;
}
};

Ok(())
Expand Down Expand Up @@ -411,9 +411,9 @@ pub(crate) unsafe fn fd_sync(
.as_descriptor(wasi::__WASI_RIGHTS_FD_SYNC, 0)?
.as_file()?;
match file {
Handle::OsHandle(fd) => fd.sync_all().map_err(Into::into),
Handle::VirtualFile(virt) => virt.sync(),
Handle::Stream(_) => {
Descriptor::OsHandle(fd) => fd.sync_all().map_err(Into::into),
Descriptor::VirtualFile(virt) => virt.sync(),
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand Down Expand Up @@ -485,7 +485,7 @@ pub(crate) unsafe fn fd_write(
}

pub(crate) unsafe fn fd_advise(
wasi_ctx: &WasiCtx,
wasi_ctx: &mut WasiCtx,
_memory: &mut [u8],
fd: wasi::__wasi_fd_t,
offset: wasi::__wasi_filesize_t,
Expand All @@ -501,14 +501,14 @@ pub(crate) unsafe fn fd_advise(
);

let file = wasi_ctx
.get_fd_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_ADVISE, 0)?
.as_handle();
.get_fd_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_ADVISE, 0)?
.as_file_mut()?;

match file {
Handle::OsHandle(fd) => hostcalls_impl::fd_advise(&fd, advice, offset, len),
Handle::VirtualFile(virt) => virt.advise(advice, offset, len),
Handle::Stream(_) => {
Descriptor::OsHandle(fd) => hostcalls_impl::fd_advise(&fd, advice, offset, len),
Descriptor::VirtualFile(virt) => virt.advise(advice, offset, len),
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand All @@ -531,7 +531,7 @@ pub(crate) unsafe fn fd_allocate(
.as_file()?;

match file {
Handle::OsHandle(fd) => {
Descriptor::OsHandle(fd) => {
let metadata = fd.metadata()?;

let current_size = metadata.len();
Expand All @@ -547,8 +547,8 @@ pub(crate) unsafe fn fd_allocate(
Ok(())
}
}
Handle::VirtualFile(virt) => virt.allocate(offset, len),
Handle::Stream(_) => {
Descriptor::VirtualFile(virt) => virt.allocate(offset, len),
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand Down Expand Up @@ -829,9 +829,9 @@ pub(crate) unsafe fn fd_filestat_get(
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_GET, 0)?
.as_file()?;
let host_filestat = match fd {
Handle::OsHandle(fd) => hostcalls_impl::fd_filestat_get(&fd)?,
Handle::VirtualFile(virt) => virt.filestat_get()?,
Handle::Stream(_) => {
Descriptor::OsHandle(fd) => hostcalls_impl::fd_filestat_get(&fd)?,
Descriptor::VirtualFile(virt) => virt.filestat_get()?,
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand Down Expand Up @@ -868,7 +868,7 @@ pub(crate) unsafe fn fd_filestat_set_times(
}

pub(crate) fn fd_filestat_set_times_impl(
file: &Handle,
file: &Descriptor,
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
Expand Down Expand Up @@ -901,9 +901,9 @@ pub(crate) fn fd_filestat_set_times_impl(
None
};
match file {
Handle::OsHandle(fd) => set_file_handle_times(fd, atim, mtim).map_err(Into::into),
Handle::VirtualFile(virt) => virt.filestat_set_times(atim, mtim),
Handle::Stream(_) => {
Descriptor::OsHandle(fd) => set_file_handle_times(fd, atim, mtim).map_err(Into::into),
Descriptor::VirtualFile(virt) => virt.filestat_set_times(atim, mtim),
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand All @@ -929,9 +929,9 @@ pub(crate) unsafe fn fd_filestat_set_size(
return Err(Error::E2BIG);
}
match file {
Handle::OsHandle(fd) => fd.set_len(st_size).map_err(Into::into),
Handle::VirtualFile(virt) => virt.filestat_set_size(st_size),
Handle::Stream(_) => {
Descriptor::OsHandle(fd) => fd.set_len(st_size).map_err(Into::into),
Descriptor::VirtualFile(virt) => virt.filestat_set_size(st_size),
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand Down Expand Up @@ -1240,11 +1240,11 @@ pub(crate) unsafe fn fd_readdir(
}

let host_bufused = match file {
HandleMut::OsHandle(file) => {
Descriptor::OsHandle(file) => {
copy_entities(hostcalls_impl::fd_readdir(file, cookie)?, host_buf)?
}
HandleMut::VirtualFile(virt) => copy_entities(virt.readdir(cookie)?, host_buf)?,
HandleMut::Stream(_) => {
Descriptor::VirtualFile(virt) => copy_entities(virt.readdir(cookie)?, host_buf)?,
_ => {
unreachable!(
"implementation error: fd should have been checked to not be a stream already"
);
Expand Down
2 changes: 1 addition & 1 deletion crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ pub(crate) fn path_filestat_set_times(
.access_mode(AccessMode::FILE_WRITE_ATTRIBUTES.bits())
.open(path)?;
let modifiable_fd = Descriptor::OsHandle(OsHandle::from(file));
fd_filestat_set_times_impl(&modifiable_fd.as_handle(), st_atim, st_mtim, fst_flags)
fd_filestat_set_times_impl(&modifiable_fd, st_atim, st_mtim, fst_flags)
}

pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
Expand Down

0 comments on commit 0c571c6

Please sign in to comment.