use std::future::Future;
use std::io;
use std::os::fd::RawFd;

use crate::Fd;
use crate::addr::SockAddr;

pub trait RecvMsgPacket {
    fn msg_mut_ptr(&mut self) -> *mut libc::msghdr;
}

pub trait SendMsgPacket {
    fn msg_ptr(&mut self) -> *const libc::msghdr;
}

pub trait SubmitOps: Sized {
    fn submit_accept(self, fd: Fd)
    -> impl Future<Output = io::Result<(RawFd, SockAddr)>> + 'static;

    fn submit_read<B>(self, fd: Fd, buf: B) -> impl Future<Output = (io::Result<u32>, B)> + 'static
    where
        B: AsMut<[u8]> + Unpin + 'static;

    fn submit_send_raw<B>(
        self,
        fd: Fd,
        buf: B,
        len: usize,
    ) -> impl Future<Output = (io::Result<u32>, B)> + 'static
    where
        B: AsRef<[u8]> + Unpin + 'static;

    fn submit_sendmsg_raw<P>(
        self,
        fd: Fd,
        packet: P,
    ) -> impl Future<Output = (io::Result<u32>, P)> + 'static
    where
        P: SendMsgPacket + Unpin + 'static;

    fn submit_recvmsg_raw<P>(
        self,
        fd: Fd,
        packet: P,
    ) -> impl Future<Output = (io::Result<u32>, P)> + 'static
    where
        P: RecvMsgPacket + Unpin + 'static;
}
