use socket2::SockAddr;
#[cfg(target_os = "windows")]
pub use crate::driver::op::ConnectNamedPipe;
pub use crate::driver::op::{Accept, RecvFromImpl, RecvImpl, SendImpl, SendToImpl};
use crate::{
    buf::{AsIoSlicesMut, BufWrapper, IntoInner, IoBuf, IoBufMut, VectoredBufWrapper, WrapBuf},
    driver::{sockaddr_storage, socklen_t, RawFd},
    BufResult,
};
pub(crate) trait BufResultExt {
    fn map_advanced(self) -> Self;
}
impl<T: AsIoSlicesMut> BufResultExt for BufResult<usize, T> {
    fn map_advanced(self) -> Self {
        let (res, buffer) = self;
        let (res, buffer) = (res.map(|res| (res, ())), buffer).map_advanced();
        let res = res.map(|(res, _)| res);
        (res, buffer)
    }
}
impl<T: AsIoSlicesMut, O> BufResultExt for BufResult<(usize, O), T> {
    fn map_advanced(self) -> Self {
        let (res, mut buffer) = self;
        if let Ok((init, _)) = &res {
            unsafe {
                buffer.set_init(*init);
            }
        }
        (res, buffer)
    }
}
pub(crate) trait RecvResultExt {
    type RecvFromResult;
    fn map_addr(self) -> Self::RecvFromResult;
}
impl<T> RecvResultExt for BufResult<usize, (T, sockaddr_storage, socklen_t)> {
    type RecvFromResult = BufResult<(usize, SockAddr), T>;
    fn map_addr(self) -> Self::RecvFromResult {
        let (res, (buffer, addr_buffer, addr_size)) = self;
        let res = res.map(|res| {
            let addr = unsafe { SockAddr::new(addr_buffer, addr_size) };
            (res, addr)
        });
        (res, buffer)
    }
}
#[derive(Debug)]
pub struct ReadAt<T: IoBufMut> {
    pub(crate) fd: RawFd,
    pub(crate) offset: usize,
    pub(crate) buffer: BufWrapper<T>,
}
impl<T: IoBufMut> ReadAt<T> {
    pub fn new(fd: RawFd, offset: usize, buffer: T) -> Self {
        Self {
            fd,
            offset,
            buffer: BufWrapper::new(buffer),
        }
    }
}
impl<T: IoBufMut> IntoInner for ReadAt<T> {
    type Inner = BufWrapper<T>;
    fn into_inner(self) -> Self::Inner {
        self.buffer
    }
}
#[derive(Debug)]
pub struct WriteAt<T: IoBuf> {
    pub(crate) fd: RawFd,
    pub(crate) offset: usize,
    pub(crate) buffer: BufWrapper<T>,
}
impl<T: IoBuf> WriteAt<T> {
    pub fn new(fd: RawFd, offset: usize, buffer: T) -> Self {
        Self {
            fd,
            offset,
            buffer: BufWrapper::new(buffer),
        }
    }
}
impl<T: IoBuf> IntoInner for WriteAt<T> {
    type Inner = BufWrapper<T>;
    fn into_inner(self) -> Self::Inner {
        self.buffer
    }
}
pub struct Sync {
    pub(crate) fd: RawFd,
    #[allow(dead_code)]
    pub(crate) datasync: bool,
}
impl Sync {
    pub fn new(fd: RawFd, datasync: bool) -> Self {
        Self { fd, datasync }
    }
}
pub struct Connect {
    pub(crate) fd: RawFd,
    pub(crate) addr: SockAddr,
}
impl Connect {
    pub fn new(fd: RawFd, addr: SockAddr) -> Self {
        Self { fd, addr }
    }
}
pub type Recv<T> = RecvImpl<BufWrapper<T>>;
pub type RecvVectored<T> = RecvImpl<VectoredBufWrapper<T>>;
pub type Send<T> = SendImpl<BufWrapper<T>>;
pub type SendVectored<T> = SendImpl<VectoredBufWrapper<T>>;
pub type RecvFrom<T> = RecvFromImpl<BufWrapper<T>>;
pub type RecvFromVectored<T> = RecvFromImpl<VectoredBufWrapper<T>>;
pub type SendTo<T> = SendToImpl<BufWrapper<T>>;
pub type SendToVectored<T> = SendToImpl<VectoredBufWrapper<T>>;