use core::fmt::Debug;
use std::fmt::{Display, Formatter, Write};
use std::sync::Arc;
use crate::redaction_engine_builder::RedactionEngineBuilder;
use crate::redaction_engine_inner::RedactionEngineInner;
use crate::{DataClass, RedactedDebug, RedactedDisplay, RedactedToString};
#[derive(Clone, Default)]
pub struct RedactionEngine {
inner: Arc<RedactionEngineInner>,
}
impl RedactionEngine {
#[must_use]
pub fn builder() -> RedactionEngineBuilder {
RedactionEngineBuilder::new()
}
#[must_use]
pub(crate) fn new(mut inner: RedactionEngineInner) -> Self {
inner.shrink();
Self { inner: Arc::new(inner) }
}
#[must_use]
pub fn would_redact(&self, data_class: &DataClass) -> bool {
self.inner.would_redact(data_class)
}
pub fn redacted_debug(&self, value: &impl RedactedDebug, output: &mut impl Write) -> core::fmt::Result {
struct DebugFormatter<'a, RD>
where
RD: RedactedDebug + ?Sized,
{
engine: &'a RedactionEngine,
value: &'a RD,
}
impl<RD> Debug for DebugFormatter<'_, RD>
where
RD: RedactedDebug + ?Sized,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.value.fmt(self.engine, f)
}
}
let d = DebugFormatter { engine: self, value };
write!(output, "{d:?}")
}
pub fn redacted_display(&self, value: &impl RedactedDisplay, output: &mut impl Write) -> core::fmt::Result {
struct DisplayFormatter<'a, RD>
where
RD: RedactedDisplay + ?Sized,
{
engine: &'a RedactionEngine,
value: &'a RD,
}
impl<RD> Display for DisplayFormatter<'_, RD>
where
RD: RedactedDisplay + ?Sized,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.value.fmt(self.engine, f)
}
}
let d = DisplayFormatter { engine: self, value };
write!(output, "{d}")
}
pub fn redacted_to_string(&self, value: &impl RedactedToString) -> String {
value.to_redacted_string(self)
}
pub fn redact(&self, data_class: impl AsRef<DataClass>, value: impl AsRef<str>, output: &mut impl Write) -> core::fmt::Result {
let data_class_ref = data_class.as_ref();
let value_str = value.as_ref();
if let Some(redactor) = self.inner.resolve(data_class_ref) {
redactor.redact(data_class_ref, value_str, output)
} else {
output.write_str(value_str)
}
}
}
impl Debug for RedactionEngine {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.inner.fmt(f)
}
}