diff --git a/Cargo.toml b/Cargo.toml index dcdbcc2..8724464 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,5 +25,8 @@ features = [ [target.'cfg(unix)'.dependencies] rustix = "0.31.3" +[target.'cfg(windows)'.dependencies] +io-lifetimes = { version = "0.4.0", default-features = false } + [dev-dependencies] tempfile = "3.0.8" diff --git a/src/lib.rs b/src/lib.rs index 9d3d619..6547cb0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ #![forbid(future_incompatible)] #![deny(missing_debug_implementations, nonstandard_style)] #![cfg_attr(doc, warn(missing_docs, rustdoc::missing_doc_code_examples))] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] mod read_guard; mod rw_lock; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 3c6391e..6e7af2a 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -4,12 +4,12 @@ cfg_if! { if #[cfg(unix)] { mod unix; pub use unix::*; - pub(crate) use std::os::unix::prelude::AsRawFd as AsRaw; + pub(crate) use rustix::fd::AsFd as AsRaw; } else if #[cfg(windows)] { mod windows; pub use windows::*; #[doc(no_inline)] - pub(crate) use std::os::windows::prelude::AsRawHandle as AsRaw; + pub(crate) use io_lifetimes::AsHandle as AsRaw; } else { mod unsupported; pub use unsupported; diff --git a/src/sys/unix/read_guard.rs b/src/sys/unix/read_guard.rs index 6d67187..cbc82c3 100644 --- a/src/sys/unix/read_guard.rs +++ b/src/sys/unix/read_guard.rs @@ -1,21 +1,21 @@ +use rustix::fd::AsFd; use rustix::fs::{flock, FlockOperation}; use std::ops; -use std::os::unix::io::AsRawFd; use super::RwLock; #[derive(Debug)] -pub struct RwLockReadGuard<'lock, T: AsRawFd> { +pub struct RwLockReadGuard<'lock, T: AsFd> { lock: &'lock RwLock, } -impl<'lock, T: AsRawFd> RwLockReadGuard<'lock, T> { +impl<'lock, T: AsFd> RwLockReadGuard<'lock, T> { pub(crate) fn new(lock: &'lock RwLock) -> Self { Self { lock } } } -impl ops::Deref for RwLockReadGuard<'_, T> { +impl ops::Deref for RwLockReadGuard<'_, T> { type Target = T; #[inline] @@ -24,7 +24,7 @@ impl ops::Deref for RwLockReadGuard<'_, T> { } } -impl Drop for RwLockReadGuard<'_, T> { +impl Drop for RwLockReadGuard<'_, T> { #[inline] fn drop(&mut self) { let _ = flock(&self.lock.as_fd(), FlockOperation::Unlock).ok(); diff --git a/src/sys/unix/rw_lock.rs b/src/sys/unix/rw_lock.rs index 9c6fc7b..ef3eaa0 100644 --- a/src/sys/unix/rw_lock.rs +++ b/src/sys/unix/rw_lock.rs @@ -1,16 +1,15 @@ -use rustix::fd::BorrowedFd; +use rustix::fd::AsFd; use rustix::fs::{flock, FlockOperation}; use std::io::{self, Error, ErrorKind}; -use std::os::unix::io::AsRawFd; use super::{RwLockReadGuard, RwLockWriteGuard}; #[derive(Debug)] -pub struct RwLock { +pub struct RwLock { pub(crate) inner: T, } -impl RwLock { +impl RwLock { #[inline] pub fn new(inner: T) -> Self { RwLock { inner } @@ -57,14 +56,4 @@ impl RwLock { { self.inner } - - #[inline] - pub(crate) fn as_fd(&self) -> BorrowedFd<'_> { - // Safety: We assume that `self.inner`'s file descriptor is valid for - // at least the lifetime of `self`. - // - // Once I/O safety is stablized in std, we can switch the public API to - // use `AsFd` instead of `AsRawFd` and eliminate this `unsafe` block. - unsafe { BorrowedFd::borrow_raw_fd(self.inner.as_raw_fd()) } - } } diff --git a/src/sys/unix/write_guard.rs b/src/sys/unix/write_guard.rs index a12bdf9..64d0a08 100644 --- a/src/sys/unix/write_guard.rs +++ b/src/sys/unix/write_guard.rs @@ -1,21 +1,21 @@ +use rustix::fd::AsFd; use rustix::fs::{flock, FlockOperation}; use std::ops; -use std::os::unix::io::AsRawFd; use super::RwLock; #[derive(Debug)] -pub struct RwLockWriteGuard<'lock, T: AsRawFd> { +pub struct RwLockWriteGuard<'lock, T: AsFd> { lock: &'lock mut RwLock, } -impl<'lock, T: AsRawFd> RwLockWriteGuard<'lock, T> { +impl<'lock, T: AsFd> RwLockWriteGuard<'lock, T> { pub(crate) fn new(lock: &'lock mut RwLock) -> Self { Self { lock } } } -impl ops::Deref for RwLockWriteGuard<'_, T> { +impl ops::Deref for RwLockWriteGuard<'_, T> { type Target = T; #[inline] @@ -24,14 +24,14 @@ impl ops::Deref for RwLockWriteGuard<'_, T> { } } -impl ops::DerefMut for RwLockWriteGuard<'_, T> { +impl ops::DerefMut for RwLockWriteGuard<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.lock.inner } } -impl Drop for RwLockWriteGuard<'_, T> { +impl Drop for RwLockWriteGuard<'_, T> { #[inline] fn drop(&mut self) { let _ = flock(&self.lock.as_fd(), FlockOperation::Unlock).ok(); diff --git a/src/sys/windows/read_guard.rs b/src/sys/windows/read_guard.rs index 88258eb..af902d8 100644 --- a/src/sys/windows/read_guard.rs +++ b/src/sys/windows/read_guard.rs @@ -1,3 +1,4 @@ +use io_lifetimes::AsHandle; use windows_sys::Win32::Storage::FileSystem::UnlockFile; use std::ops; @@ -7,11 +8,11 @@ use super::utils::syscall; use super::RwLock; #[derive(Debug)] -pub struct RwLockReadGuard<'lock, T: AsRawHandle> { +pub struct RwLockReadGuard<'lock, T: AsHandle> { pub(crate) lock: &'lock RwLock, } -impl ops::Deref for RwLockReadGuard<'_, T> { +impl ops::Deref for RwLockReadGuard<'_, T> { type Target = T; #[inline] @@ -20,10 +21,10 @@ impl ops::Deref for RwLockReadGuard<'_, T> { } } -impl Drop for RwLockReadGuard<'_, T> { +impl Drop for RwLockReadGuard<'_, T> { #[inline] fn drop(&mut self) { - let handle = self.lock.inner.as_raw_handle(); + let handle = self.lock.inner.as_handle().as_raw_handle(); syscall(unsafe { UnlockFile(handle, 0, 0, 1, 0) }) .expect("Could not unlock the file descriptor"); } diff --git a/src/sys/windows/rw_lock.rs b/src/sys/windows/rw_lock.rs index 15ded19..8f01741 100644 --- a/src/sys/windows/rw_lock.rs +++ b/src/sys/windows/rw_lock.rs @@ -1,3 +1,4 @@ +use io_lifetimes::AsHandle; use std::io::{self, Error, ErrorKind}; use std::os::windows::io::AsRawHandle; @@ -9,11 +10,11 @@ use super::utils::{syscall, Overlapped}; use super::{RwLockReadGuard, RwLockWriteGuard}; #[derive(Debug)] -pub struct RwLock { +pub struct RwLock { pub(crate) inner: T, } -impl RwLock { +impl RwLock { #[inline] pub fn new(inner: T) -> Self { RwLock { inner } @@ -22,7 +23,7 @@ impl RwLock { #[inline] pub fn read(&self) -> io::Result> { // See: https://stackoverflow.com/a/9186532, https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex - let handle = self.inner.as_raw_handle(); + let handle = self.inner.as_handle().as_raw_handle(); let overlapped = Overlapped::zero(); let flags = 0; syscall(unsafe { LockFileEx(handle, flags, 0, 1, 0, overlapped.raw()) })?; @@ -31,7 +32,7 @@ impl RwLock { #[inline] pub fn try_read(&self) -> io::Result> { - let handle = self.inner.as_raw_handle(); + let handle = self.inner.as_handle().as_raw_handle(); let overlapped = Overlapped::zero(); let flags = LOCKFILE_FAIL_IMMEDIATELY; @@ -43,7 +44,7 @@ impl RwLock { #[inline] pub fn write(&mut self) -> io::Result> { // See: https://stackoverflow.com/a/9186532, https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex - let handle = self.inner.as_raw_handle(); + let handle = self.inner.as_handle().as_raw_handle(); let overlapped = Overlapped::zero(); let flags = LOCKFILE_EXCLUSIVE_LOCK; syscall(unsafe { LockFileEx(handle, flags, 0, 1, 0, overlapped.raw()) })?; @@ -52,7 +53,7 @@ impl RwLock { #[inline] pub fn try_write(&mut self) -> io::Result> { - let handle = self.inner.as_raw_handle(); + let handle = self.inner.as_handle().as_raw_handle(); let overlapped = Overlapped::zero(); let flags = LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK; diff --git a/src/sys/windows/write_guard.rs b/src/sys/windows/write_guard.rs index cb1d9b3..6e22e34 100644 --- a/src/sys/windows/write_guard.rs +++ b/src/sys/windows/write_guard.rs @@ -1,3 +1,4 @@ +use io_lifetimes::AsHandle; use windows_sys::Win32::Storage::FileSystem::UnlockFile; use std::ops; @@ -7,11 +8,11 @@ use super::utils::syscall; use super::RwLock; #[derive(Debug)] -pub struct RwLockWriteGuard<'lock, T: AsRawHandle> { +pub struct RwLockWriteGuard<'lock, T: AsHandle> { pub(crate) lock: &'lock mut RwLock, } -impl ops::Deref for RwLockWriteGuard<'_, T> { +impl ops::Deref for RwLockWriteGuard<'_, T> { type Target = T; #[inline] @@ -20,17 +21,17 @@ impl ops::Deref for RwLockWriteGuard<'_, T> { } } -impl ops::DerefMut for RwLockWriteGuard<'_, T> { +impl ops::DerefMut for RwLockWriteGuard<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.lock.inner } } -impl Drop for RwLockWriteGuard<'_, T> { +impl Drop for RwLockWriteGuard<'_, T> { #[inline] fn drop(&mut self) { - let handle = self.lock.inner.as_raw_handle(); + let handle = self.lock.inner.as_handle().as_raw_handle(); syscall(unsafe { UnlockFile(handle, 0, 0, 1, 0) }) .expect("Could not unlock the file descriptor"); }