ntr-io 0.0.1

Idiomatic NT APIs on Rust (I/O)
use super as io;
use super::raw::{AsRawHandle, RawHandle};
#[cfg(feature = "net")]
use super::raw::{AsRawSocket, RawSocket};

pub use windows::Win32::Foundation::GetLastError;
pub use windows::Win32::Foundation::{CloseHandle, DuplicateHandle};
pub use windows::Win32::Foundation::{DUPLICATE_HANDLE_OPTIONS, DUPLICATE_SAME_ACCESS};
pub use windows::Win32::Foundation::{HANDLE as WindowsHandle, INVALID_HANDLE_VALUE};
pub use windows::Win32::System::Threading::GetCurrentProcess;

#[cfg(feature = "net")]
pub use windows::Win32::Foundation::{HANDLE_FLAG_INHERIT, HANDLE_FLAGS, SetHandleInformation};
#[cfg(feature = "net")]
pub use windows::Win32::Networking::WinSock::WSAGetLastError;
#[cfg(feature = "net")]
pub use windows::Win32::Networking::WinSock::WSAPROTOCOL_INFOW;
#[cfg(feature = "net")]
pub use windows::Win32::Networking::WinSock::closesocket;
#[cfg(feature = "net")]
pub use windows::Win32::Networking::WinSock::{INVALID_SOCKET, SOCKET as WindowsSocket};
#[cfg(feature = "net")]
pub use windows::Win32::Networking::WinSock::{WSA_FLAG_NO_HANDLE_INHERIT, WSA_FLAG_OVERLAPPED};
#[cfg(feature = "net")]
pub use windows::Win32::Networking::WinSock::{WSADuplicateSocketW, WSASocketW};
#[cfg(feature = "net")]
pub use windows::Win32::Networking::WinSock::{WSAEINVAL, WSAEPROTOTYPE};
#[cfg(feature = "net")]
pub use windows::Win32::System::Threading::GetCurrentProcessId;

pub trait AsWindowsHandle {
    fn as_windows_handle(&self) -> WindowsHandle;
}

#[cfg(feature = "net")]
pub trait AsWindowsSocket {
    fn as_windows_socket(&self) -> WindowsSocket;
}

impl AsWindowsHandle for RawHandle {
    fn as_windows_handle(&self) -> WindowsHandle {
        WindowsHandle(*self)
    }
}

impl AsRawHandle for WindowsHandle {
    fn as_raw_handle(&self) -> io::raw::RawHandle {
        self.0
    }
}

#[cfg(feature = "net")]
impl AsWindowsSocket for RawSocket {
    fn as_windows_socket(&self) -> WindowsSocket {
        WindowsSocket(*self as _)
    }
}

#[cfg(feature = "net")]
impl AsRawSocket for WindowsSocket {
    fn as_raw_socket(&self) -> RawSocket {
        self.0 as _
    }
}

#[allow(unused)]
pub trait IsZero {
    fn is_zero(&self) -> bool;
}

macro_rules! impl_is_zero {
    ($($t:ident)*) => ($(impl IsZero for $t {
        fn is_zero(&self) -> bool {
            *self == 0
        }
    })*)
}

impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }

#[allow(unused)]
pub fn cvt<I: IsZero>(i: I) -> io::Result<I> {
    if i.is_zero() {
        unsafe { GetLastError() }.ok()?;
        Ok(i)
    } else {
        Ok(i)
    }
}

#[allow(unused)]
pub trait IsMinusOne {
    fn is_minus_one(&self) -> bool;
}

macro_rules! impl_is_minus_one {
    ($($t:ident)*) => ($(impl IsMinusOne for $t {
        fn is_minus_one(&self) -> bool {
            *self == -1
        }
    })*)
}

impl_is_minus_one! { i8 i16 i32 i64 isize }

#[allow(unused)]
#[cfg(feature = "net")]
pub fn net_cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
    if t.is_minus_one() {
        Err(io::Error::from_os_code(unsafe { WSAGetLastError() }.0))
    } else {
        Ok(t)
    }
}