Make wasi-common-std-sync's dependency on system-interface private. (#4784)

* Make wasi-common-std-sync's dependency on system-interface private.

Change some `pub` functions which exposed system-interface types to be
non-`pub`.

And, change `from_sysif_fdflags` functions to `get_fd_flags` functions
that take `impl AsFilelike` arguments instead of system-interface types.

With these changes, system-interface is no longer exposed in the
public API.

* Add a public API for `is_read_write` too.

Implementors using types implementing `AsFilelike` may want to use the
same `is_read_write` logic, without explicitly depending on
system-interface, so provide a function that provides that.
This commit is contained in:
Dan Gohman
2022-08-26 11:39:00 -07:00
committed by GitHub
parent c1f9736938
commit a68fa86aad
3 changed files with 69 additions and 20 deletions

View File

@@ -31,6 +31,7 @@ rustix = { version = "0.35.6", features = ["fs"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
once_cell = "1.12.0" once_cell = "1.12.0"
io-extras = "0.15.0" io-extras = "0.15.0"
rustix = { version = "0.35.6", features = ["net"] }
[target.'cfg(windows)'.dependencies.windows-sys] [target.'cfg(windows)'.dependencies.windows-sys]
version = "0.36.0" version = "0.36.0"

View File

@@ -1,5 +1,6 @@
use cap_fs_ext::MetadataExt; use cap_fs_ext::MetadataExt;
use fs_set_times::{SetTimes, SystemTimeSpec}; use fs_set_times::{SetTimes, SystemTimeSpec};
use io_lifetimes::AsFilelike;
use is_terminal::IsTerminal; use is_terminal::IsTerminal;
use std::any::Any; use std::any::Any;
use std::convert::TryInto; use std::convert::TryInto;
@@ -48,8 +49,8 @@ impl WasiFile for File {
Ok(filetype_from(&meta.file_type())) Ok(filetype_from(&meta.file_type()))
} }
async fn get_fdflags(&mut self) -> Result<FdFlags, Error> { async fn get_fdflags(&mut self) -> Result<FdFlags, Error> {
let fdflags = self.0.get_fd_flags()?; let fdflags = get_fd_flags(&self.0)?;
Ok(from_sysif_fdflags(fdflags)) Ok(fdflags)
} }
async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> { async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> {
if fdflags.intersects( if fdflags.intersects(
@@ -187,7 +188,10 @@ impl AsFd for File {
self.0.as_fd() self.0.as_fd()
} }
} }
pub fn convert_systimespec(t: Option<wasi_common::SystemTimeSpec>) -> Option<SystemTimeSpec> {
pub(crate) 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)) => {
Some(SystemTimeSpec::Absolute(t.into_std())) Some(SystemTimeSpec::Absolute(t.into_std()))
@@ -197,7 +201,7 @@ pub fn convert_systimespec(t: Option<wasi_common::SystemTimeSpec>) -> Option<Sys
} }
} }
pub fn to_sysif_fdflags(f: wasi_common::file::FdFlags) -> system_interface::fs::FdFlags { pub(crate) fn to_sysif_fdflags(f: wasi_common::file::FdFlags) -> system_interface::fs::FdFlags {
let mut out = system_interface::fs::FdFlags::empty(); let mut out = system_interface::fs::FdFlags::empty();
if f.contains(wasi_common::file::FdFlags::APPEND) { if f.contains(wasi_common::file::FdFlags::APPEND) {
out |= system_interface::fs::FdFlags::APPEND; out |= system_interface::fs::FdFlags::APPEND;
@@ -216,7 +220,12 @@ pub fn to_sysif_fdflags(f: wasi_common::file::FdFlags) -> system_interface::fs::
} }
out out
} }
pub fn from_sysif_fdflags(f: system_interface::fs::FdFlags) -> wasi_common::file::FdFlags {
/// Return the file-descriptor flags for a given file-like object.
///
/// This returns the flags needed to implement [`WasiFile::get_fdflags`].
pub fn get_fd_flags<Filelike: AsFilelike>(f: Filelike) -> io::Result<wasi_common::file::FdFlags> {
let f = f.as_filelike().get_fd_flags()?;
let mut out = wasi_common::file::FdFlags::empty(); let mut out = wasi_common::file::FdFlags::empty();
if f.contains(system_interface::fs::FdFlags::APPEND) { if f.contains(system_interface::fs::FdFlags::APPEND) {
out |= wasi_common::file::FdFlags::APPEND; out |= wasi_common::file::FdFlags::APPEND;
@@ -233,9 +242,10 @@ pub fn from_sysif_fdflags(f: system_interface::fs::FdFlags) -> wasi_common::file
if f.contains(system_interface::fs::FdFlags::SYNC) { if f.contains(system_interface::fs::FdFlags::SYNC) {
out |= wasi_common::file::FdFlags::SYNC; out |= wasi_common::file::FdFlags::SYNC;
} }
out Ok(out)
} }
pub fn convert_advice(advice: Advice) -> system_interface::fs::Advice {
fn convert_advice(advice: Advice) -> system_interface::fs::Advice {
match advice { match advice {
Advice::Normal => system_interface::fs::Advice::Normal, Advice::Normal => system_interface::fs::Advice::Normal,
Advice::Sequential => system_interface::fs::Advice::Sequential, Advice::Sequential => system_interface::fs::Advice::Sequential,

View File

@@ -1,7 +1,5 @@
#[cfg(windows)] #[cfg(windows)]
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket}; use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
#[cfg(unix)]
use io_lifetimes::AsFilelike;
use io_lifetimes::AsSocketlike; use io_lifetimes::AsSocketlike;
#[cfg(unix)] #[cfg(unix)]
use io_lifetimes::{AsFd, BorrowedFd}; use io_lifetimes::{AsFd, BorrowedFd};
@@ -105,8 +103,8 @@ macro_rules! wasi_listen_write_impl {
} }
#[cfg(unix)] #[cfg(unix)]
async fn get_fdflags(&mut self) -> Result<FdFlags, Error> { async fn get_fdflags(&mut self) -> Result<FdFlags, Error> {
let fdflags = self.0.as_filelike().get_fd_flags()?; let fdflags = get_fd_flags(&self.0)?;
Ok(from_sysif_fdflags(fdflags)) Ok(fdflags)
} }
async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> { async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> {
if fdflags == wasi_common::file::FdFlags::NONBLOCK { if fdflags == wasi_common::file::FdFlags::NONBLOCK {
@@ -193,8 +191,8 @@ macro_rules! wasi_stream_write_impl {
} }
#[cfg(unix)] #[cfg(unix)]
async fn get_fdflags(&mut self) -> Result<FdFlags, Error> { async fn get_fdflags(&mut self) -> Result<FdFlags, Error> {
let fdflags = self.0.as_filelike().get_fd_flags()?; let fdflags = get_fd_flags(&self.0)?;
Ok(from_sysif_fdflags(fdflags)) Ok(fdflags)
} }
async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> { async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> {
if fdflags == wasi_common::file::FdFlags::NONBLOCK { if fdflags == wasi_common::file::FdFlags::NONBLOCK {
@@ -230,7 +228,7 @@ macro_rules! wasi_stream_write_impl {
Ok(val) Ok(val)
} }
async fn readable(&self) -> Result<(), Error> { async fn readable(&self) -> Result<(), Error> {
let (readable, _writeable) = self.0.is_read_write()?; let (readable, _writeable) = is_read_write(&self.0)?;
if readable { if readable {
Ok(()) Ok(())
} else { } else {
@@ -238,7 +236,7 @@ macro_rules! wasi_stream_write_impl {
} }
} }
async fn writable(&self) -> Result<(), Error> { async fn writable(&self) -> Result<(), Error> {
let (_readable, writeable) = self.0.is_read_write()?; let (_readable, writeable) = is_read_write(&self.0)?;
if writeable { if writeable {
Ok(()) Ok(())
} else { } else {
@@ -303,10 +301,50 @@ pub fn filetype_from(ft: &cap_std::fs::FileType) -> FileType {
} }
} }
pub fn from_sysif_fdflags(f: system_interface::fs::FdFlags) -> wasi_common::file::FdFlags { /// Return the file-descriptor flags for a given file-like object.
let mut out = wasi_common::file::FdFlags::empty(); ///
if f.contains(system_interface::fs::FdFlags::NONBLOCK) { /// This returns the flags needed to implement [`WasiFile::get_fdflags`].
out |= wasi_common::file::FdFlags::NONBLOCK; pub fn get_fd_flags<Socketlike: AsSocketlike>(
f: Socketlike,
) -> io::Result<wasi_common::file::FdFlags> {
// On Unix-family platforms, we can use the same system call that we'd use
// for files on sockets here.
#[cfg(not(windows))]
{
let mut out = wasi_common::file::FdFlags::empty();
if f.get_fd_flags()?
.contains(system_interface::fs::FdFlags::NONBLOCK)
{
out |= wasi_common::file::FdFlags::NONBLOCK;
}
Ok(out)
}
// On Windows, sockets are different, and there is no direct way to
// query for the non-blocking flag. We can get a sufficient approximation
// by testing whether a zero-length `recv` appears to block.
#[cfg(windows)]
match rustix::net::recv(f, &mut [], rustix::net::RecvFlags::empty()) {
Ok(_) => Ok(wasi_common::file::FdFlags::empty()),
Err(rustix::io::Errno::WOULDBLOCK) => Ok(wasi_common::file::FdFlags::NONBLOCK),
Err(e) => Err(e.into()),
}
}
/// Return the file-descriptor flags for a given file-like object.
///
/// This returns the flags needed to implement [`WasiFile::get_fdflags`].
pub fn is_read_write<Socketlike: AsSocketlike>(f: Socketlike) -> io::Result<(bool, bool)> {
// On Unix-family platforms, we have an `IsReadWrite` impl.
#[cfg(not(windows))]
{
f.is_read_write()
}
// On Windows, we only have a `TcpStream` impl, so make a view first.
#[cfg(windows)]
{
f.as_socketlike_view::<std::net::TcpStream>()
.is_read_write()
} }
out
} }