#[cfg(feature = "json")]
use serde::Serialize;
#[cfg(feature = "json")]
use serde_json::Value as JsonValue;
use super::{
traits::{Redactable, SensitiveWithPolicy},
wrappers::SensitiveValue,
};
use crate::policy::RedactionPolicy;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RedactedOutput {
Text(String),
#[cfg(feature = "json")]
Json(JsonValue),
}
pub trait ToRedactedOutput {
#[must_use]
fn to_redacted_output(&self) -> RedactedOutput;
}
impl ToRedactedOutput for RedactedOutput {
fn to_redacted_output(&self) -> RedactedOutput {
self.clone()
}
}
impl<T, P> ToRedactedOutput for SensitiveValue<T, P>
where
T: SensitiveWithPolicy<P>,
P: RedactionPolicy,
{
fn to_redacted_output(&self) -> RedactedOutput {
RedactedOutput::Text(self.redacted())
}
}
pub struct RedactedOutputRef<'a, T: ?Sized>(&'a T);
impl<T> ToRedactedOutput for RedactedOutputRef<'_, T>
where
T: Redactable + Clone + std::fmt::Debug,
{
fn to_redacted_output(&self) -> RedactedOutput {
RedactedOutput::Text(format!("{:?}", self.0.clone().redact()))
}
}
pub trait RedactedOutputExt {
fn redacted_output(&self) -> RedactedOutputRef<'_, Self>
where
Self: Sized;
}
impl<T> RedactedOutputExt for T
where
T: Redactable + Clone + std::fmt::Debug,
{
fn redacted_output(&self) -> RedactedOutputRef<'_, Self> {
RedactedOutputRef(self)
}
}
#[cfg(feature = "json")]
pub struct RedactedJson {
value: JsonValue,
}
#[cfg(feature = "json")]
impl RedactedJson {
#[cfg(feature = "slog")]
pub(crate) fn new(value: JsonValue) -> Self {
Self { value }
}
#[cfg(feature = "slog")]
pub(crate) fn value(&self) -> &JsonValue {
&self.value
}
}
#[cfg(feature = "json")]
impl ToRedactedOutput for RedactedJson {
fn to_redacted_output(&self) -> RedactedOutput {
RedactedOutput::Json(self.value.clone())
}
}
#[cfg(feature = "json")]
pub struct RedactedJsonRef<'a, T: ?Sized>(&'a T);
#[cfg(feature = "json")]
impl<T> ToRedactedOutput for RedactedJsonRef<'_, T>
where
T: Redactable + Clone + Serialize,
{
fn to_redacted_output(&self) -> RedactedOutput {
let redacted = self.0.clone().redact();
match serde_json::to_value(redacted) {
Ok(json) => RedactedOutput::Json(json),
Err(err) => RedactedOutput::Text(format!("Failed to serialize redacted value: {err}")),
}
}
}
#[cfg(feature = "json")]
pub trait RedactedJsonExt {
fn redacted_json(&self) -> RedactedJsonRef<'_, Self>
where
Self: Sized;
}
#[cfg(feature = "json")]
impl<T> RedactedJsonExt for T
where
T: Redactable + Clone + Serialize,
{
fn redacted_json(&self) -> RedactedJsonRef<'_, Self> {
RedactedJsonRef(self)
}
}