use cfg_if::cfg_if;
use core::cmp;
use core::future::Future;
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::task::{Context, Poll};
use std::io::Error;
#[cfg(feature = "async-io")]
use std::net::{TcpStream, UdpSocket};
pub trait AsyncPeek {
fn poll_peek(
self: Pin<&mut Self>,
ctx: &mut Context,
buf: &mut [u8],
) -> Poll<Result<usize, Error>>;
}
pub trait AsyncPeekExt: AsyncPeek {
fn peek<'peek>(&'peek mut self, buf: &'peek mut [u8]) -> Peek<'peek, Self>
where
Self: Unpin,
{
Peek { peek: self, buf }
}
}
pub struct Peek<'peek, P: ?Sized> {
peek: &'peek mut P,
buf: &'peek mut [u8],
}
#[allow(unused)]
macro_rules! impl_for_net {
($net:ty) => {
impl AsyncPeek for $net {
fn poll_peek(
self: Pin<&mut Self>,
ctx: &mut Context,
buf: &mut [u8],
) -> Poll<Result<usize, Error>> {
let fut = (&*self).peek(buf);
ufut::pin!(fut);
fut.poll(ctx)
}
}
};
}
impl AsyncPeek for &[u8] {
fn poll_peek(
self: Pin<&mut Self>,
_: &mut Context,
buf: &mut [u8],
) -> Poll<Result<usize, Error>> {
let len = cmp::min(buf.len(), self.len());
buf[0..len].copy_from_slice(&self[0..len]);
Poll::Ready(Ok(len))
}
}
impl<T> AsyncPeek for &mut T
where
T: AsyncPeek + Unpin + ?Sized,
{
fn poll_peek(
mut self: Pin<&mut Self>,
ctx: &mut Context,
buf: &mut [u8],
) -> Poll<Result<usize, Error>> {
Pin::new(&mut **self).poll_peek(ctx, buf)
}
}
impl<T> AsyncPeek for Box<T>
where
T: AsyncPeek + Unpin + ?Sized,
{
fn poll_peek(
mut self: Pin<&mut Self>,
ctx: &mut Context,
buf: &mut [u8],
) -> Poll<Result<usize, Error>> {
Pin::new(&mut **self).poll_peek(ctx, buf)
}
}
impl<T> AsyncPeek for Pin<T>
where
T: DerefMut + Unpin,
<T as Deref>::Target: AsyncPeek,
{
fn poll_peek(
self: Pin<&mut Self>,
ctx: &mut Context,
buf: &mut [u8],
) -> Poll<Result<usize, Error>> {
self.get_mut().as_mut().poll_peek(ctx, buf)
}
}
cfg_if! {
if #[cfg(feature = "async-io")] {
impl_for_net!(async_io::Async<TcpStream>);
impl_for_net!(async_io::Async<UdpSocket>);
impl_for_net!(&async_io::Async<TcpStream>);
impl_for_net!(&async_io::Async<UdpSocket>);
}
}
cfg_if! {
if #[cfg(feature = "async-net")] {
impl_for_net!(async_net::TcpStream);
impl_for_net!(async_net::UdpSocket);
impl_for_net!(&async_net::TcpStream);
impl_for_net!(&async_net::UdpSocket);
}
}
impl<P: AsyncPeek + ?Sized> AsyncPeekExt for P {}
impl<P: AsyncPeek + Unpin> Future for Peek<'_, P> {
type Output = Result<usize, Error>;
fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> {
let this = &mut *self;
Pin::new(&mut this.peek).poll_peek(ctx, this.buf)
}
}