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:
@@ -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"
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user