mod chunked;
mod fixed;
use crate::request::Metadata;
use futures_io::AsyncWrite;
use std::io::Result;
use std::pin::Pin;
use std::task::{Context, Poll};
#[derive(Debug, Eq, PartialEq)]
enum Mode<'socket, Socket: AsyncWrite + ?Sized> {
Fixed(fixed::Send<'socket, Socket>),
Chunked(chunked::Send<'socket, Socket>),
}
#[derive(Debug, Eq, PartialEq)]
pub struct Send<'socket, Socket: AsyncWrite + ?Sized> {
inner: Mode<'socket, Socket>,
metadata: Metadata,
}
impl<'socket, Socket: AsyncWrite + ?Sized> Send<'socket, Socket> {
pub(crate) fn new_fixed(
socket: Pin<&'socket mut Socket>,
metadata: Metadata,
length: u64,
) -> Self {
Self {
inner: Mode::Fixed(fixed::Send::new(socket, length)),
metadata,
}
}
pub(crate) fn new_chunked(socket: Pin<&'socket mut Socket>, metadata: Metadata) -> Self {
Self {
inner: Mode::Chunked(chunked::Send::new(socket)),
metadata,
}
}
pub fn hint_length(&mut self, length: u64) {
match &mut self.inner {
Mode::Fixed(_) => (),
Mode::Chunked(inner) => inner.hint_length(length),
}
}
pub async fn finish(self) -> Result<Metadata> {
match self.inner {
Mode::Fixed(inner) => inner.finish(),
Mode::Chunked(inner) => inner.finish().await?,
}
Ok(self.metadata)
}
}
impl<Socket: AsyncWrite + ?Sized> AsyncWrite for Send<'_, Socket> {
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize>> {
match self.inner {
Mode::Fixed(ref mut inner) => Pin::new(inner).poll_write(cx, buf),
Mode::Chunked(ref mut inner) => Pin::new(inner).poll_write(cx, buf),
}
}
fn poll_write_vectored(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[std::io::IoSlice<'_>],
) -> Poll<Result<usize>> {
match self.inner {
Mode::Fixed(ref mut inner) => Pin::new(inner).poll_write_vectored(cx, bufs),
Mode::Chunked(ref mut inner) => Pin::new(inner).poll_write_vectored(cx, bufs),
}
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
match self.inner {
Mode::Fixed(ref mut inner) => Pin::new(inner).poll_flush(cx),
Mode::Chunked(ref mut inner) => Pin::new(inner).poll_flush(cx),
}
}
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
match self.inner {
Mode::Fixed(ref mut inner) => Pin::new(inner).poll_close(cx),
Mode::Chunked(ref mut inner) => Pin::new(inner).poll_close(cx),
}
}
}
#[cfg(test)]
mod test {
use futures_io::AsyncWrite;
use std::pin::Pin;
pub(super) trait AsyncWriteExt: AsyncWrite {
fn write<'a>(self: Pin<&'a mut Self>, data: &'a [u8]) -> WriteFuture<'a, Self> {
WriteFuture { sink: self, data }
}
}
impl<W: AsyncWrite + ?Sized> AsyncWriteExt for W {}
#[derive(Debug)]
pub(super) struct WriteFuture<'a, T: AsyncWrite + ?Sized> {
sink: Pin<&'a mut T>,
data: &'a [u8],
}
impl<T: AsyncWrite + ?Sized> Future for WriteFuture<'_, T> {
type Output = std::io::Result<usize>;
fn poll(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
let data = self.data;
self.sink.as_mut().poll_write(cx, data)
}
}
}