voidio 0.1.7

VOID I/O - High-performance Cross-platform I/O for Rust.
use std::{mem::MaybeUninit, net::{SocketAddr, ToSocketAddrs}};
use super::{sys::SockAddrIn6, *};

#[cfg(unix)]
pub type SocketRaw = i32;
#[cfg(windows)]
pub type SocketRaw = usize;


#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct Socket(SocketRaw);

impl <'a>Socket {
    #[inline(always)]
    #[allow(unused_variables)]
    pub fn new<AF: AddressFamily, ST: SocketType, P: Protocol>(af: AF, st: ST, protocol: P) -> Result<Socket>
    where
        (AF, ST, P): ValidSocket,
    {
        xsocket(AF::DOMAIN, ST::TYPE, P::PROTOCOL)
    }

    #[inline(always)]
    pub fn raw_new(af: i32, socket_type: i32, protocol: i32) -> Result<Socket> {
        xsocket(af, socket_type, protocol)
    }

    #[inline(always)]
    pub fn bind<A: ToSocketAddrs>(self, addr: A) -> Result<()> {
        xbind(self, addr)
    }

    #[inline(always)]
    pub fn connect<A: ToSocketAddrs>(self, addr: A) -> Result<()> {
        xconnect(self, addr)
    }

    #[inline(always)]
    pub fn listen(self, backlog: i32) -> Result<()> {
        xlisten(self, backlog)
    }

    #[inline(always)]
    pub fn accept(self) -> Result<Socket> {
        xaccept(self)
    }

    #[inline(always)]
    pub fn send(self, buf: &[u8], flags: i32) -> Result<usize> {
        xsend(self, buf, flags)
    }

    #[inline(always)]
    pub fn recv(self, buf: &mut [u8], flags: i32) -> Result<usize> {
        xrecv(self, buf, flags)
    }

    #[inline(always)]
    pub fn _send_to<A: SocketAddressBuffer>(self, buf: &[u8], addr: &A, flags: i32) -> Result<usize> {
        xsendto(self, buf, flags, addr)
    }
    #[inline(always)]
    pub fn send_to(self, buf: &[u8], addr: &SocketAddr, flags: i32) -> Result<usize> {
        unsafe {
            match addr {
                SocketAddr::V4(v4) => {
                    let saddr = SocketAddrSrcV4::from_socket_addr(v4);
                    let result = sys::sendto(
                        self.as_raw(),
                        buf.as_ptr() as *const _,
                        buf.len() as i32,
                        flags,
                        saddr.as_raw_ptr() as *const _,
                        saddr.len() as i32
                    );
                    if result < 0 { Err(std::io::Error::last_os_error()) } else { Ok(result as usize) }
                },
                SocketAddr::V6(v6) => {
                    let saddr = SocketAddrSrcV6::from_socket_addr(v6);
                    let result = sys::sendto(
                        self.as_raw(),
                        buf.as_ptr() as *const _,
                        buf.len() as i32,
                        flags,
                        saddr.as_raw_ptr() as *const _,
                        saddr.len() as i32
                    );
                    if result < 0 { Err(std::io::Error::last_os_error()) } else { Ok(result as usize) }
                }
            }
        }
    }

    #[inline(always)]
    pub fn sendmmsg<A: SocketAddressBuffer>(self, bufs: &[(&[u8], &A)], flags: i32) -> Result<usize> {
        xsendmmsg(self, bufs, flags)
    }

    #[inline(always)]
    pub fn popmsgv4(self, data_buf: &mut [u8], data_len: &mut usize, flags: i32) -> Result<SocketAddrSrcV4> {
        xrecvfrom_v4(self, data_buf, data_len, flags)
    }
    
    pub fn popmsgv6(self, data_buf: &mut [u8], data_len: &mut usize, flags: i32) -> Result<SocketAddrSrcV6> {
        xrecvfrom_v6(self, data_buf, data_len, flags)
    }
    /*
    #[inline(always)]
    pub fn _popmsg(self, data_buf: &mut [u8], data_len: &mut usize, flags: i32) -> Result<SocketAddrSrc> {
        _popmsg(self, data_buf, data_len, flags)
    }
*/
    #[inline(always)]
    pub fn popmsg(self, data_buf: &mut [u8], data_len: &mut usize, flags: i32) -> Result<SocketAddr> {
        popmsg(self, data_buf, data_len, flags)
    }

    #[inline(always)]
    pub fn vecrecv<IpvXInbox>(self, inbox: &mut IpvXInbox, flags: i32) -> Result<usize>
    where IpvXInbox: IpBucket {
        vecrecv(self, inbox, flags)
    }

    #[inline(always)]
    pub fn recv_from_v4(self, data_buf: &mut [u8], data_len: &mut usize, flags: i32) -> Result<SocketAddrSrcV4> {
        xrecvfrom_v4(self, data_buf, data_len, flags)
    }

    #[inline(always)]
    pub fn recv_from_v6(self, data_buf: &mut [u8], data_len: &mut usize, flags: i32) -> Result<SocketAddrSrcV6> {
        xrecvfrom_v6(self, data_buf, data_len, flags)
    }

    #[inline(always)]
    pub fn peer_name_v4(self) -> Result<SockAddrIn> {
    let mut addr_buf = MaybeUninit::<SockAddrIn>::uninit();
        xgetpeername(self, &mut addr_buf).unwrap();
        Ok(unsafe { addr_buf.assume_init() })

    }
    
    #[inline(always)]
    pub fn peer_name_v6(self) -> Result<SockAddrIn6> {
        let mut addr_buf = MaybeUninit::<SockAddrIn6>::uninit();
        xgetpeername(self, &mut addr_buf).unwrap();
        Ok(unsafe { addr_buf.assume_init() })
    }

    #[inline(always)]
    pub fn close(self) -> Result<()> {
        xclose(self)
    }
    
    #[inline(always)]
    #[allow(unused_variables)]
    pub fn set_socket_option<O: SocketOption>(&self, option: O, value: O::ValueType) -> Result<()>
    where 
        O::ValueType: 'static
    {
        if TypeId::of::<O::ValueType>() == TypeId::of::<std::time::Duration>() {
            let duration = unsafe { &*( &value as *const _ as *const std::time::Duration) };
            let timeval = sys::TimeVal::from_duration(*duration);
            &timeval as *const _ as *const _;
            xsetsockopt(*self, O::level(), O::name(), &timeval, O::len())
        } else {
            &value as *const O::ValueType as *const _;
            xsetsockopt(*self, O::level(), O::name(), &value, O::len())
        }
    }

    #[inline(always)]
    pub fn as_raw(&self) -> SocketRaw {
        self.0
    }
}