From 9c561014f3c4278c0991290c898713f8e9c928e8 Mon Sep 17 00:00:00 2001 From: cel 🌸 Date: Thu, 3 Apr 2025 03:09:35 +0100 Subject: feat: xml logging --- src/loggable.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/loggable.rs (limited to 'src/loggable.rs') 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 { + log_buffer: Vec, + #[pin] + writer: W, +} + +impl Loggable { + 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 { + let log: Vec = mem::replace(&mut self.log_buffer, Vec::new()); + log + } +} + +impl Display for Loggable { + 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 AsyncWrite for Loggable { + fn poll_write( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &[u8], + ) -> std::task::Poll> { + 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> { + 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> { + let this = self.project(); + Poll::Ready(ready!(this.writer.poll_shutdown(cx))) + } +} -- cgit