use std::ops::{Deref, DerefMut};
#[cfg(feature = "json")]
use serde::Serialize;
use super::output::{RedactedOutput, ToRedactedOutput};
pub struct NotSensitive<T>(pub T);
impl<T> NotSensitive<T> {
#[must_use]
pub fn inner(&self) -> &T {
&self.0
}
}
impl<T> Deref for NotSensitive<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for NotSensitive<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> std::fmt::Display for NotSensitive<T>
where
T: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
impl<T> std::fmt::Debug for NotSensitive<T>
where
T: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.0, f)
}
}
pub struct NotSensitiveDisplay<T>(pub T);
impl<T> NotSensitiveDisplay<T> {
#[must_use]
pub fn inner(&self) -> &T {
&self.0
}
}
impl<T> ToRedactedOutput for NotSensitiveDisplay<T>
where
T: std::fmt::Display,
{
fn to_redacted_output(&self) -> RedactedOutput {
RedactedOutput::Text(self.0.to_string())
}
}
impl<T> std::fmt::Display for NotSensitiveDisplay<T>
where
T: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
impl<T> std::fmt::Debug for NotSensitiveDisplay<T>
where
T: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
pub struct NotSensitiveDebug<T>(pub T);
impl<T> NotSensitiveDebug<T> {
#[must_use]
pub fn inner(&self) -> &T {
&self.0
}
}
impl<T> ToRedactedOutput for NotSensitiveDebug<T>
where
T: std::fmt::Debug,
{
fn to_redacted_output(&self) -> RedactedOutput {
RedactedOutput::Text(format!("{:?}", self.0))
}
}
impl<T> std::fmt::Debug for NotSensitiveDebug<T>
where
T: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("NotSensitiveDebug")
.field(&self.to_redacted_output())
.finish()
}
}
#[cfg(feature = "json")]
pub struct NotSensitiveJson<'a, T: ?Sized>(&'a T);
#[cfg(feature = "json")]
impl<T: ?Sized> NotSensitiveJson<'_, T> {
#[must_use]
pub fn inner(&self) -> &T {
self.0
}
}
#[cfg(feature = "json")]
impl<T> ToRedactedOutput for NotSensitiveJson<'_, T>
where
T: Serialize + ?Sized,
{
fn to_redacted_output(&self) -> RedactedOutput {
match serde_json::to_value(self.0) {
Ok(json) => RedactedOutput::Json(json),
Err(err) => {
RedactedOutput::Text(format!("Failed to serialize not-sensitive value: {err}"))
}
}
}
}
#[cfg(feature = "json")]
impl<T> std::fmt::Debug for NotSensitiveJson<'_, T>
where
T: Serialize + ?Sized,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("NotSensitiveJson")
.field(&self.to_redacted_output())
.finish()
}
}
pub trait NotSensitiveExt: Sized {
fn not_sensitive(&self) -> NotSensitive<&Self> {
NotSensitive(self)
}
}
impl<T: Sized> NotSensitiveExt for T {}
pub trait NotSensitiveDisplayExt: Sized + std::fmt::Display {
fn not_sensitive_display(&self) -> NotSensitiveDisplay<&Self> {
NotSensitiveDisplay(self)
}
}
impl<T> NotSensitiveDisplayExt for T where T: std::fmt::Display {}
pub trait NotSensitiveDebugExt: Sized + std::fmt::Debug {
fn not_sensitive_debug(&self) -> NotSensitiveDebug<&Self> {
NotSensitiveDebug(self)
}
}
impl<T> NotSensitiveDebugExt for T where T: std::fmt::Debug {}
#[cfg(feature = "json")]
pub trait NotSensitiveJsonExt {
fn not_sensitive_json(&self) -> NotSensitiveJson<'_, Self>
where
Self: Sized;
}
#[cfg(feature = "json")]
impl<T> NotSensitiveJsonExt for T
where
T: Serialize,
{
fn not_sensitive_json(&self) -> NotSensitiveJson<'_, Self> {
NotSensitiveJson(self)
}
}