heveanly 0.1.0

C is the heavenly option
Documentation
#[cfg(feature = "std")]
use std::os::fd::AsRawFd;
#[cfg(feature = "std")]
use std::{io, mem};

#[cfg(feature = "std")]
use crate::{AsUninitBytes, Iovec, IovecMut};

#[repr(transparent)]
#[cfg_attr(feature = "nightly", rustc_layout_scalar_valid_range_start(0x0000_0000))]
#[cfg_attr(feature = "nightly", rustc_layout_scalar_valid_range_end(0x7fff_ffff))]
#[cfg_attr(feature = "nightly", rustc_nonnull_optimization_guaranteed)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Fd(i32);

#[cold]
#[inline]
const fn badf() -> Option<Fd> {
   None
}

impl Fd {
   pub const fn new(fd: i32) -> Option<Self> {
      if fd < 0 {
         return badf();
      }
      #[allow(unused_unsafe)]
      Some(unsafe { Self(fd) })
   }

   #[inline(always)]
   pub const unsafe fn new_unchecked(fd: i32) -> Self {
      Self(fd)
   }

   #[inline(always)]
   pub fn get(self) -> i32 {
      self.0
   }
}

impl From<Fd> for i32 {
   #[inline(always)]
   fn from(value: Fd) -> Self {
      value.0
   }
}

#[cfg(feature = "std")]
impl AsRawFd for Fd {
   fn as_raw_fd(&self) -> i32 {
      self.0
   }
}

#[cfg(feature = "std")]
impl io::Write for Fd {
   #[inline]
   fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
      Fd::write(*self, buf).map_err(Into::into)
   }

   #[inline]
   fn write_vectored(&mut self, bufs: &[io::IoSlice]) -> io::Result<usize> {
      self
         .writev(unsafe { mem::transmute::<&[io::IoSlice], &[Iovec]>(bufs) })
         .map_err(Into::into)
   }

   #[cfg(feature = "nightly")]
   #[inline(always)]
   fn is_write_vectored(&self) -> bool {
      true
   }

   #[inline(always)]
   fn flush(&mut self) -> io::Result<()> {
      Ok(())
   }
}

#[cfg(feature = "std")]
impl io::Read for Fd {
   #[inline]
   fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
      Fd::read(*self, buf.as_uninit_bytes_mut()).map_err(Into::into)
   }

   #[inline]
   fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut]) -> io::Result<usize> {
      self
         .readv(unsafe { mem::transmute::<&mut [io::IoSliceMut], &mut [IovecMut]>(bufs) })
         .map_err(Into::into)
   }

   #[cfg(feature = "nightly")]
   #[inline(always)]
   fn is_read_vectored(&self) -> bool {
      true
   }
}

pub trait AsFd {
   fn as_fd(&self) -> Fd;
}

#[cold]
#[track_caller]
#[inline(never)]
fn panic_badf() -> ! {
   panic!("bad file descriptor");
}

#[cfg(feature = "std")]
impl<T: AsRawFd> AsFd for T {
   #[inline]
   fn as_fd(&self) -> Fd {
      let fd = self.as_raw_fd();
      if fd < 0 {
         panic_badf();
      }
      #[allow(unused_unsafe)]
      unsafe {
         Fd(fd)
      }
   }
}

#[cfg(not(feature = "std"))]
impl AsFd for i32 {
   #[inline]
   fn as_fd(&self) -> Fd {
      if *self < 0 {
         panic_badf();
      }
      #[allow(unused_unsafe)]
      unsafe {
         Fd(*self)
      }
   }
}