use std::{ io::Write, pin::Pin, task::{Context, Poll}, }; use pin_project::pin_project; use tokio::io::{self, AsyncWrite}; #[pin_project] pub struct AsyncTeeWriter<'a, W> where W: AsyncWrite + Unpin, { #[pin] writer: &'a mut W, buffer: Vec, } impl<'a, W> AsyncTeeWriter<'a, W> where W: AsyncWrite + Unpin, { pub fn new(writer: &'a mut W) -> Self { Self { writer, buffer: Vec::new(), } } pub fn into_vec(self) -> Vec { self.buffer } } impl<'a, W> AsyncWrite for AsyncTeeWriter<'a, W> where W: AsyncWrite + Unpin, { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { let mut this = self.project(); match this.writer.as_mut().poll_write(cx, buf) { Poll::Ready(res) => { this.buffer .write_all(buf) .expect("Failed to write to internal tee buffer"); Poll::Ready(res) } Poll::Pending => Poll::Pending, } } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().writer.as_mut().poll_flush(cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().writer.as_mut().poll_shutdown(cx) } }