use std::{
any::Any,
future::Future,
io,
net::SocketAddr,
sync::Arc,
task::{Context, Poll},
};
use bytes::BytesMut;
use qbase::net::route::Route;
pub mod handy;
mod factory;
pub use factory::*;
use crate::bind_uri::BindUri;
pub trait IO: Send + Sync + Any {
fn bind_uri(&self) -> BindUri;
fn bound_addr(&self) -> io::Result<SocketAddr>;
fn max_segment_size(&self) -> io::Result<usize>;
fn max_segments(&self) -> io::Result<usize>;
fn poll_send(
&self,
cx: &mut Context,
pkts: &[io::IoSlice],
route: Route,
) -> Poll<io::Result<usize>>;
fn poll_recv(
&self,
cx: &mut Context,
pkts: &mut [BytesMut],
route: &mut [Route],
) -> Poll<io::Result<usize>>;
fn poll_close(&mut self, cx: &mut Context) -> Poll<io::Result<()>>;
}
pub trait IoExt: IO {
#[inline]
fn sendmmsg(
&self,
mut bufs: &[io::IoSlice<'_>],
route: Route,
) -> impl Future<Output = io::Result<()>> + Send {
async move {
while !bufs.is_empty() {
let sent = core::future::poll_fn(|cx| self.poll_send(cx, bufs, route)).await?;
bufs = &bufs[sent..];
}
Ok(())
}
}
fn recvmmsg<'b>(
&self,
bufs: &'b mut Vec<BytesMut>,
route: &'b mut Vec<Route>,
) -> impl Future<Output = io::Result<impl Iterator<Item = (BytesMut, Route)> + Send + 'b>> + Send
{
async move {
let rcvd = std::future::poll_fn(|cx| {
let max_segments = self.max_segments()?;
let max_segment_size = self.max_segment_size()?;
bufs.resize_with(max_segments, || BytesMut::zeroed(max_segment_size));
route.resize_with(max_segments, Route::empty);
self.poll_recv(cx, bufs, route)
})
.await?;
Ok(bufs
.drain(..rcvd)
.zip(route.drain(..rcvd))
.map(|(mut seg, route)| {
(seg.split_to(seg.len().min(route.seg_size() as _)), route)
}))
}
}
#[inline]
fn close(&mut self) -> impl Future<Output = io::Result<()>> + Send {
async { core::future::poll_fn(|cx| self.poll_close(cx)).await }
}
}
impl<I: IO + ?Sized> IoExt for I {}
pub trait RefIO: Clone + Send + Sync {
type Interface: IO + ?Sized;
fn iface(&self) -> &Self::Interface;
fn same_io(&self, other: &Self) -> bool;
}
impl<I: IO + ?Sized> RefIO for Arc<I> {
type Interface = I;
#[inline]
fn iface(&self) -> &Self::Interface {
self.as_ref()
}
fn same_io(&self, other: &Self) -> bool {
Arc::ptr_eq(self, other)
}
}