diff options
Diffstat (limited to 'src/loggable.rs')
-rw-r--r-- | src/loggable.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/loggable.rs b/src/loggable.rs new file mode 100644 index 0000000..dd69668 --- /dev/null +++ b/src/loggable.rs @@ -0,0 +1,67 @@ +use std::{fmt::Display, mem, pin::pin, task::Poll}; + +use futures::ready; +use pin_project::pin_project; +pub use tokio::io::AsyncWrite; + +#[pin_project] +#[derive(Debug)] +pub struct Loggable<W> { + log_buffer: Vec<u8>, + #[pin] + writer: W, +} + +impl<W> Loggable<W> { + pub fn new(writer: W) -> Self { + Self { + log_buffer: Vec::new(), + writer, + } + } + + pub fn into_inner(self) -> W { + self.writer + } + + pub fn take_log(&mut self) -> Vec<u8> { + let log: Vec<u8> = mem::replace(&mut self.log_buffer, Vec::new()); + log + } +} + +impl<W: AsyncWrite + Unpin + Send> Display for Loggable<W> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let str = str::from_utf8(&self.log_buffer).unwrap_or("buffer to string conversion failed"); + f.write_str(str) + } +} + +impl<W: AsyncWrite + Unpin + Send> AsyncWrite for Loggable<W> { + fn poll_write( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &[u8], + ) -> std::task::Poll<Result<usize, std::io::Error>> { + let this = self.as_mut().project(); + let ready = ready!(this.writer.poll_write(cx, buf)); + self.log_buffer.extend_from_slice(buf); + Poll::Ready(ready) + } + + fn poll_flush( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll<Result<(), std::io::Error>> { + let this = self.project(); + Poll::Ready(ready!(this.writer.poll_flush(cx))) + } + + fn poll_shutdown( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll<Result<(), std::io::Error>> { + let this = self.project(); + Poll::Ready(ready!(this.writer.poll_shutdown(cx))) + } +} |