use std::{
io::{self, Cursor, Read},
pin::Pin,
task::{Context, Poll},
};
pub trait Body {
fn poll_chunk(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>>;
fn poll_chunk_size_hint(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<io::Result<(usize, Option<usize>)>>;
fn size_hint(&self) -> (usize, Option<usize>);
}
impl Body for () {
fn poll_chunk(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
_buf: &mut [u8],
) -> Poll<io::Result<usize>> {
Poll::Ready(Ok(0))
}
fn poll_chunk_size_hint(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
) -> Poll<io::Result<(usize, Option<usize>)>> {
Poll::Ready(Ok(self.size_hint()))
}
fn size_hint(&self) -> (usize, Option<usize>) {
exact_size_hint(0)
}
}
impl<T> Body for Cursor<T>
where
T: AsRef<[u8]> + Unpin,
{
fn poll_chunk(
mut self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
Poll::Ready(self.as_mut().read(buf))
}
fn poll_chunk_size_hint(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
) -> Poll<io::Result<(usize, Option<usize>)>> {
Poll::Ready(Ok(self.size_hint()))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let position: usize = self.position().try_into().unwrap();
let length = self.get_ref().as_ref().len().saturating_sub(position);
exact_size_hint(length)
}
}
fn exact_size_hint(size: usize) -> (usize, Option<usize>) {
(size, Some(size))
}