use std::marker::PhantomData;
#[cfg(feature = "json")]
use serde::Serialize;
use super::{
redact::RedactableMapper,
traits::{RedactableWithMapper, SensitiveWithPolicy},
};
use crate::policy::RedactionPolicy;
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SensitiveValue<T, P>(T, PhantomData<P>);
impl<T, P> SensitiveValue<T, P>
where
T: SensitiveWithPolicy<P>,
P: RedactionPolicy,
{
#[must_use]
pub fn redacted(&self) -> String {
let policy = P::policy();
self.0.redacted_string(&policy)
}
}
impl<T, P> RedactableWithMapper for SensitiveValue<T, P>
where
T: SensitiveWithPolicy<P>,
P: RedactionPolicy,
{
fn redact_with<M: RedactableMapper>(self, mapper: &M) -> Self {
let redacted = mapper.map_sensitive::<T, P>(self.0);
Self(redacted, PhantomData)
}
}
impl<T, P> From<T> for SensitiveValue<T, P> {
fn from(value: T) -> Self {
Self(value, PhantomData)
}
}
impl<T, P> SensitiveValue<T, P> {
#[must_use]
pub fn expose(&self) -> &T {
&self.0
}
pub fn expose_mut(&mut self) -> &mut T {
&mut self.0
}
#[must_use]
pub fn into_inner(self) -> T {
self.0
}
}
impl<T, P> std::fmt::Debug for SensitiveValue<T, P>
where
T: SensitiveWithPolicy<P>,
P: RedactionPolicy,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("SensitiveValue")
.field(&self.redacted())
.finish()
}
}
#[cfg(feature = "json")]
impl<T, P> Serialize for SensitiveValue<T, P>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NotSensitiveValue<T>(pub T);
impl<T> RedactableWithMapper for NotSensitiveValue<T> {
fn redact_with<M: RedactableMapper>(self, _mapper: &M) -> Self {
self
}
}
impl<T> From<T> for NotSensitiveValue<T> {
fn from(value: T) -> Self {
Self(value)
}
}
impl<T> std::ops::Deref for NotSensitiveValue<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> std::ops::DerefMut for NotSensitiveValue<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for NotSensitiveValue<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("NotSensitiveValue").field(&self.0).finish()
}
}
#[cfg(feature = "json")]
impl<T: Serialize> Serialize for NotSensitiveValue<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}