use std::{
borrow::Cow,
fmt::{
self,
Debug,
Display,
Formatter,
},
};
use crate::{
LogSafeText,
MaskingPolicy,
RedactedText,
Sensitivity,
};
#[must_use = "format or otherwise consume the redacted value"]
#[derive(Clone, PartialEq, Eq)]
pub enum RedactedValue<'a> {
Text(
RedactedText<'a>,
),
Some(
RedactedText<'a>,
),
None,
}
impl<'a> RedactedValue<'a> {
#[inline(always)]
pub fn opaque(level: Sensitivity, masking: &'a MaskingPolicy) -> Self {
Self::Text(RedactedText::new(Cow::Borrowed(masking.mask_opaque(level))))
}
}
impl Debug for RedactedValue<'_> {
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Text(text) => Debug::fmt(text.as_str(), formatter),
Self::Some(text) => {
formatter.debug_tuple("Some").field(&text.as_str()).finish()
}
Self::None => formatter.write_str("None"),
}
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for RedactedValue<'_> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Self::Text(text) => serializer.serialize_str(text.as_str()),
Self::Some(text) => serializer.serialize_some(text.as_str()),
Self::None => serializer.serialize_none(),
}
}
}
impl Display for RedactedValue<'_> {
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Text(text) => Display::fmt(&log_safe(text), formatter),
Self::Some(text) => {
formatter.write_str("Some(")?;
Display::fmt(&log_safe(text), formatter)?;
formatter.write_str(")")
}
Self::None => formatter.write_str("None"),
}
}
}
#[inline(always)]
fn log_safe<'a>(text: &'a RedactedText<'_>) -> LogSafeText<'a> {
RedactedText::new(Cow::Borrowed(text.as_str())).escape_for_log()
}