use some better traits

This commit is contained in:
Pat Hickey
2021-04-15 16:00:11 -07:00
parent 9880d09f1f
commit d2a98ced53
4 changed files with 45 additions and 47 deletions

8
Cargo.lock generated
View File

@@ -285,6 +285,12 @@ version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
[[package]]
name = "bytes"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
[[package]] [[package]]
name = "cap-fs-ext" name = "cap-fs-ext"
version = "0.13.7" version = "0.13.7"
@@ -2819,6 +2825,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5" checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg 1.0.1",
"bytes",
"memchr",
"num_cpus", "num_cpus",
"pin-project-lite", "pin-project-lite",
"tokio-macros", "tokio-macros",

View File

@@ -15,7 +15,7 @@ include = ["src/**/*", "LICENSE" ]
wasi-common = { path = "../", version = "0.26.0" } wasi-common = { path = "../", version = "0.26.0" }
wasi-cap-std-sync = { path = "../cap-std-sync", version = "0.26.0" } wasi-cap-std-sync = { path = "../cap-std-sync", version = "0.26.0" }
wiggle = { path = "../../wiggle", version = "0.26.0" } wiggle = { path = "../../wiggle", version = "0.26.0" }
tokio = { version = "1.5.0", features = [ "rt", "fs", "time" ] } tokio = { version = "1.5.0", features = [ "rt", "fs", "time" , "io-util"] }
cap-std = "0.13.7" cap-std = "0.13.7"
cap-fs-ext = "0.13.7" cap-fs-ext = "0.13.7"
cap-time-ext = "0.13.7" cap-time-ext = "0.13.7"

View File

@@ -12,56 +12,52 @@ use wasi_common::{
}; };
mod internal { mod internal {
use std::sync::{Mutex, MutexGuard};
#[cfg(not(windows))] #[cfg(not(windows))]
use unsafe_io::os::posish::{AsRawFd, RawFd}; use unsafe_io::os::posish::{AsRawFd, RawFd};
#[cfg(windows)] #[cfg(windows)]
use unsafe_io::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket}; use unsafe_io::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
use unsafe_io::OwnsRaw; use unsafe_io::OwnsRaw;
use wasi_common::Error;
// This internal type wraps tokio's File so that we can impl the // This internal type wraps tokio's File so that we can impl the
// `AsUnsafeFile` trait. We impl this on an internal type, rather than on // `AsUnsafeFile` trait. We impl this on an internal type, rather than on
// super::File, because we don't want consumers of this library to be able // super::File, because we don't want consumers of this library to be able
// to use our `AsUnsafeFile`. // to use our `AsUnsafeFile`.
pub(super) struct Internal(pub(super) tokio::fs::File); // Mutex is required because this type requires internal mutation for the
// tokio AsyncWriteExt methods to work, and must be Send.
pub(super) struct Internal(Mutex<tokio::fs::File>);
impl Internal {
pub fn new(f: tokio::fs::File) -> Self {
Internal(Mutex::new(f))
}
pub fn inner(&self) -> MutexGuard<tokio::fs::File> {
self.0.lock().unwrap()
}
}
#[cfg(not(windows))] #[cfg(not(windows))]
impl AsRawFd for Internal { impl AsRawFd for Internal {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd() self.inner().as_raw_fd()
} }
} }
#[cfg(windows)] #[cfg(windows)]
impl AsRawHandleOrSocket for Internal { impl AsRawHandleOrSocket for Internal {
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0.as_raw_handle_or_socket() self.inner().as_raw_handle_or_socket()
} }
} }
// Safety: `Internal` owns its handle. // Safety: `Internal` owns its handle.
unsafe impl OwnsRaw for Internal {} unsafe impl OwnsRaw for Internal {}
// Tokio provides implementations of these methods, which are not
// available via AsUnsafeFile.
impl Internal {
pub async fn set_len(&self, size: u64) -> Result<(), Error> {
Ok(self.0.set_len(size).await?)
}
pub async fn sync_data(&self) -> Result<(), Error> {
Ok(self.0.sync_data().await?)
}
pub async fn sync_all(&self) -> Result<(), Error> {
Ok(self.0.sync_all().await?)
}
}
} }
pub struct File(internal::Internal); pub struct File(internal::Internal);
impl File { impl File {
pub fn from_cap_std(file: cap_std::fs::File) -> Self { pub fn from_cap_std(file: cap_std::fs::File) -> Self {
File(internal::Internal(tokio::fs::File::from_std( File(internal::Internal::new(tokio::fs::File::from_std(
file.into_std(), file.into_std(),
))) )))
} }
@@ -78,10 +74,12 @@ impl WasiFile for File {
self self
} }
async fn datasync(&self) -> Result<(), Error> { async fn datasync(&self) -> Result<(), Error> {
self.0.sync_data().await self.0.inner().sync_data().await?;
Ok(())
} }
async fn sync(&self) -> Result<(), Error> { async fn sync(&self) -> Result<(), Error> {
self.0.sync_all().await self.0.inner().sync_all().await?;
Ok(())
} }
async fn get_filetype(&self) -> Result<FileType, Error> { async fn get_filetype(&self) -> Result<FileType, Error> {
let meta = self.metadata().await?; let meta = self.metadata().await?;
@@ -116,8 +114,7 @@ impl WasiFile for File {
}) })
} }
async fn set_filestat_size(&self, size: u64) -> Result<(), Error> { async fn set_filestat_size(&self, size: u64) -> Result<(), Error> {
// Tokio asyncified this already: self.0.inner().set_len(size).await?;
self.0.set_len(size).await?;
Ok(()) Ok(())
} }
async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> { async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
@@ -141,9 +138,17 @@ impl WasiFile for File {
Ok(()) Ok(())
} }
async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> { async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {
// XXX use tokio's AsyncReadExt trait instead! use std::ops::DerefMut;
let n = self.0.read_vectored(bufs)?; use tokio::io::AsyncReadExt;
Ok(n.try_into()?) let mut nbytes: usize = 0;
for b in bufs.iter_mut() {
let n = self.0.inner().read(b.deref_mut()).await?;
nbytes += n;
if n < b.len() {
break;
}
}
Ok(nbytes.try_into()?)
} }
async fn read_vectored_at<'a>( async fn read_vectored_at<'a>(
&self, &self,
@@ -154,8 +159,9 @@ impl WasiFile for File {
Ok(n.try_into()?) Ok(n.try_into()?)
} }
async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> { async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
// XXX use tokio's AsyncWriteExt trait instead! use tokio::io::AsyncWriteExt;
let n = self.0.write_vectored(bufs)?; let mut n: usize = 0;
n += self.0.inner().write_vectored(bufs).await?;
Ok(n.try_into()?) Ok(n.try_into()?)
} }
async fn write_vectored_at<'a>( async fn write_vectored_at<'a>(
@@ -201,23 +207,6 @@ pub fn filetype_from(ft: &cap_std::fs::FileType) -> FileType {
} }
} }
#[cfg(windows)]
use std::os::windows::io::{AsRawHandle, RawHandle};
#[cfg(windows)]
impl AsRawHandle for File {
fn as_raw_handle(&self) -> RawHandle {
self.0.as_raw_handle()
}
}
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(unix)]
impl AsRawFd for File {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
pub fn convert_systimespec(t: Option<wasi_common::SystemTimeSpec>) -> Option<SystemTimeSpec> { pub fn convert_systimespec(t: Option<wasi_common::SystemTimeSpec>) -> Option<SystemTimeSpec> {
match t { match t {
Some(wasi_common::SystemTimeSpec::Absolute(t)) => { Some(wasi_common::SystemTimeSpec::Absolute(t)) => {

View File

@@ -85,6 +85,7 @@ impl WasiCtxBuilder {
pub fn stderr(self, f: Box<dyn wasi_common::WasiFile>) -> Self { pub fn stderr(self, f: Box<dyn wasi_common::WasiFile>) -> Self {
WasiCtxBuilder(self.0.stderr(f)) WasiCtxBuilder(self.0.stderr(f))
} }
// XXX our crate needs its own stdios
pub fn inherit_stdin(self) -> Self { pub fn inherit_stdin(self) -> Self {
self.stdin(Box::new(wasi_cap_std_sync::stdio::stdin())) self.stdin(Box::new(wasi_cap_std_sync::stdio::stdin()))
} }
@@ -102,7 +103,7 @@ impl WasiCtxBuilder {
dir: Dir, dir: Dir,
guest_path: impl AsRef<Path>, guest_path: impl AsRef<Path>,
) -> Result<Self, wasi_common::Error> { ) -> Result<Self, wasi_common::Error> {
let dir = Box::new(wasi_cap_std_sync::dir::Dir::from_cap_std(dir)); let dir = Box::new(crate::dir::Dir::from_cap_std(dir));
Ok(WasiCtxBuilder(self.0.preopened_dir(dir, guest_path)?)) Ok(WasiCtxBuilder(self.0.preopened_dir(dir, guest_path)?))
} }
pub fn build(self) -> Result<WasiCtx, wasi_common::Error> { pub fn build(self) -> Result<WasiCtx, wasi_common::Error> {