Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define dedicated error types for HandleOrNull and HandleOrInvalid #27

Merged
merged 9 commits into from
Apr 29, 2022
Merged
4 changes: 2 additions & 2 deletions examples/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::{
use io_lifetimes::{AsFd, FromFd, OwnedFd};

#[cfg(windows)]
use io_lifetimes::{AsHandle, FromHandle, OwnedHandle};
use io_lifetimes::{AsHandle, FromHandle, InvalidHandleError, OwnedHandle};
#[cfg(windows)]
use std::{convert::TryInto, ptr::null_mut};

Expand Down Expand Up @@ -74,7 +74,7 @@ fn main() -> io::Result<()> {
null_mut(),
)
.try_into()
.map_err(|()| io::Error::last_os_error())?;
.map_err(|_err| io::Error::last_os_error())?;

// Borrow the handle to write to it.
let mut number_of_bytes_written = 0;
Expand Down
8 changes: 4 additions & 4 deletions src/example_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#[cfg(any(unix, target_os = "wasi"))]
use crate::{BorrowedFd, OwnedFd};
#[cfg(windows)]
use crate::{BorrowedHandle, HandleOrInvalid, OwnedHandle};
use crate::{BorrowedHandle, HandleOrInvalid};

#[cfg(any(unix, target_os = "wasi"))]
use libc::{c_char, c_int, c_void, size_t, ssize_t};
Expand All @@ -30,9 +30,9 @@ extern "C" {
#[cfg(any(unix, target_os = "wasi"))]
pub use libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};

/// The Windows analogs of the above. Note the use of [`HandleOrInvalid`] as
/// the return type for `CreateFileW`, since that function is defined to return
/// [`INVALID_HANDLE_VALUE`] on error instead of null.
// The Windows analogs of the above. Note the use of [`HandleOrInvalid`] as
// the return type for `CreateFileW`, since that function is defined to return
// [`INVALID_HANDLE_VALUE`] on error instead of null.
#[cfg(windows)]
extern "system" {
pub fn CreateFileW(
Expand Down
8 changes: 6 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ pub use traits::{FromHandle, FromSocket, IntoHandle, IntoSocket};
pub use types::{BorrowedFd, OwnedFd};
#[cfg(not(io_lifetimes_use_std))]
#[cfg(windows)]
pub use types::{BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket};
pub use types::{
BorrowedHandle, BorrowedSocket, HandleOrInvalid, InvalidHandleError, NullHandleError,
OwnedHandle, OwnedSocket,
};

#[cfg(io_lifetimes_use_std)]
#[cfg(unix)]
Expand All @@ -67,7 +70,8 @@ pub use std::os::wasi::io::{AsFd, BorrowedFd, OwnedFd};
#[cfg(io_lifetimes_use_std)]
#[cfg(windows)]
pub use std::os::windows::io::{
AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket,
AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, HandleOrInvalid, InvalidHandleError,
NullHandleError, OwnedHandle, OwnedSocket,
};

// io-lifetimes defined `FromFd`/`IntoFd` traits instead of just using
Expand Down
40 changes: 34 additions & 6 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,17 +491,17 @@ impl BorrowedSocket<'_> {

#[cfg(windows)]
impl TryFrom<HandleOrInvalid> for OwnedHandle {
type Error = ();
type Error = InvalidHandleError;

#[inline]
fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, ()> {
fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
let raw = handle_or_invalid.0;
if raw == INVALID_HANDLE_VALUE {
// Don't call `CloseHandle`; it'd be harmless, except that it could
// overwrite the `GetLastError` error.
forget(handle_or_invalid);

Err(())
Err(InvalidHandleError(()))
} else {
Ok(OwnedHandle { handle: raw })
}
Expand All @@ -510,23 +510,51 @@ impl TryFrom<HandleOrInvalid> for OwnedHandle {

#[cfg(windows)]
impl TryFrom<HandleOrNull> for OwnedHandle {
type Error = ();
type Error = NullHandleError;

#[inline]
fn try_from(handle_or_null: HandleOrNull) -> Result<Self, ()> {
fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
let raw = handle_or_null.0;
if raw.is_null() {
// Don't call `CloseHandle`; it'd be harmless, except that it could
// overwrite the `GetLastError` error.
forget(handle_or_null);

Err(())
Err(NullHandleError(()))
} else {
Ok(OwnedHandle { handle: raw })
}
}
}

/// This is the error type used by [`HandleOrNull`] when attempting to convert
/// into a handle, to indicate that the value is null.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NullHandleError(());

impl fmt::Display for NullHandleError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
}
}

impl std::error::Error for NullHandleError {}

/// This is the error type used by [`HandleOrInvalid`] when attempting to
/// convert into a handle, to indicate that the value is
/// `INVALID_HANDLE_VALUE`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InvalidHandleError(());

impl fmt::Display for InvalidHandleError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
.fmt(fmt)
}
}

impl std::error::Error for InvalidHandleError {}

#[cfg(any(unix, target_os = "wasi"))]
impl AsRawFd for BorrowedFd<'_> {
#[inline]
Expand Down
6 changes: 3 additions & 3 deletions tests/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#[cfg(any(unix, windows))]
use io_lifetimes::example_ffi::*;
#[cfg(windows)]
use io_lifetimes::OwnedHandle;
use io_lifetimes::{InvalidHandleError, OwnedHandle};
#[cfg(windows)]
use std::{convert::TryInto, ptr::null_mut};
#[cfg(windows)]
Expand All @@ -29,7 +29,7 @@ fn test_file_not_found() {
#[cfg(windows)]
#[test]
fn test_file_not_found() {
let handle: Result<OwnedHandle, ()> = unsafe {
let handle: Result<OwnedHandle, InvalidHandleError> = unsafe {
CreateFileW(
[
'C' as u16, ':' as _, '/' as _, 'n' as _, 'o' as _, '/' as _, 's' as _, 'u' as _,
Expand Down Expand Up @@ -61,7 +61,7 @@ fn test_file_found() {
#[cfg(windows)]
#[test]
fn test_file_found() {
let handle: Result<OwnedHandle, ()> = unsafe {
let handle: Result<OwnedHandle, InvalidHandleError> = unsafe {
CreateFileW(
[
'C' as u16, 'a' as _, 'r' as _, 'g' as _, 'o' as _, '.' as _, 't' as _, 'o' as _,
Expand Down
4 changes: 2 additions & 2 deletions tests/niche-optimizations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use std::mem::size_of;
#[cfg(any(unix, target_os = "wasi"))]
use io_lifetimes::{BorrowedFd, OwnedFd};
#[cfg(windows)]
use io_lifetimes::{BorrowedHandle, BorrowedSocket, OwnedHandle, OwnedSocket};
use io_lifetimes::{BorrowedSocket, OwnedSocket};

#[cfg(unix)]
use std::os::unix::io::RawFd;
#[cfg(target_os = "wasi")]
use std::os::wasi::io::RawFd;
#[cfg(windows)]
use std::os::windows::io::{RawHandle, RawSocket};
use std::os::windows::io::RawSocket;

#[cfg(all(rustc_attrs, any(unix, target_os = "wasi")))]
#[test]
Expand Down