1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
//! A general wrapper to allow for feature flagged redactions.
use std::fmt::{Debug, Display, Error, Formatter};
use crate::instrumentation::MakeFmt;
use super::REDACTED;
/// A wrapper used to modify the [`Display`] and [`Debug`] implementation of the inner structure
/// based on the feature flag `unredacted-logging`. When the `unredacted-logging` feature is enabled, the
/// implementations will defer to those on `T`, when disabled they will defer to [`REDACTED`].
///
/// Note that there are [`Display`] and [`Debug`] implementations for `&T` where `T: Display`
/// and `T: Debug` respectively - wrapping references is allowed for the cases when consuming the
/// inner struct is not desired.
///
/// # Example
///
/// ```
/// # use aws_smithy_http_server::instrumentation::sensitivity::Sensitive;
/// # let address = "";
/// tracing::debug!(
/// name = %Sensitive("Alice"),
/// friends = ?Sensitive(["Bob"]),
/// address = ?Sensitive(&address)
/// );
/// ```
pub struct Sensitive<T>(pub T);
impl<T> Debug for Sensitive<T>
where
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
if cfg!(feature = "unredacted-logging") {
self.0.fmt(f)
} else {
Debug::fmt(&REDACTED, f)
}
}
}
impl<T> Display for Sensitive<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
if cfg!(feature = "unredacted-logging") {
self.0.fmt(f)
} else {
Display::fmt(&REDACTED, f)
}
}
}
/// A [`MakeFmt`] producing [`Sensitive`].
#[derive(Debug, Clone)]
pub struct MakeSensitive;
impl<T> MakeFmt<T> for MakeSensitive {
type Target = Sensitive<T>;
fn make(&self, source: T) -> Self::Target {
Sensitive(source)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug() {
let inner = "hello world";
let sensitive = Sensitive(inner);
let actual = format!("{:?}", sensitive);
let expected = if cfg!(feature = "unredacted-logging") {
format!("{:?}", inner)
} else {
format!("{:?}", REDACTED)
};
assert_eq!(actual, expected)
}
#[test]
fn display() {
let inner = "hello world";
let sensitive = Sensitive(inner);
let actual = format!("{}", sensitive);
let expected = if cfg!(feature = "unredacted-logging") {
inner.to_string()
} else {
REDACTED.to_string()
};
assert_eq!(actual, expected)
}
}