use std::io;
use std::sync::Arc;
use tracing_subscriber::fmt::MakeWriter;
use super::masker::Masker;
pub struct MaskingMakeWriter<W> {
inner: W,
masker: Arc<dyn Masker>,
}
impl<W> MaskingMakeWriter<W> {
pub fn new(inner: W, masker: Arc<dyn Masker>) -> Self {
Self { inner, masker }
}
}
impl<'a, W: MakeWriter<'a>> MakeWriter<'a> for MaskingMakeWriter<W> {
type Writer = MaskingWriter<W::Writer>;
fn make_writer(&'a self) -> Self::Writer {
MaskingWriter {
inner: self.inner.make_writer(),
masker: Arc::clone(&self.masker),
buffer: Vec::with_capacity(256),
}
}
fn make_writer_for(&'a self, meta: &tracing::Metadata<'_>) -> Self::Writer {
MaskingWriter {
inner: self.inner.make_writer_for(meta),
masker: Arc::clone(&self.masker),
buffer: Vec::with_capacity(256),
}
}
}
pub struct MaskingWriter<W: io::Write> {
inner: W,
masker: Arc<dyn Masker>,
buffer: Vec<u8>,
}
impl<W: io::Write> io::Write for MaskingWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buffer.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
if !self.buffer.is_empty() {
let output = String::from_utf8_lossy(&self.buffer);
let masked = self.masker.mask_output(&output);
self.inner.write_all(masked.as_bytes())?;
self.buffer.clear();
}
self.inner.flush()
}
}
impl<W: io::Write> Drop for MaskingWriter<W> {
fn drop(&mut self) {
if !self.buffer.is_empty() {
let output = String::from_utf8_lossy(&self.buffer);
let masked = self.masker.mask_output(&output);
let _ = self.inner.write_all(masked.as_bytes());
self.buffer.clear();
let _ = self.inner.flush();
}
}
}