use crate::{
IpAddressPolicyKind, RedactableMapper, RedactableWithFormatter, RedactionPolicy,
ScalarRedaction, SecretPolicyKind, TextPolicyKind,
policy::RecursivePolicyKind,
redaction::{
IpPolicyApplicable, IpPolicyApplicableRef, PolicyApplicable, PolicyApplicableRef,
PolicyMapper,
},
};
use super::output::PolicyFormattingOutput;
pub trait PolicyField<P: RedactionPolicy>: Sized {
#[must_use]
fn apply_field<M: RedactableMapper>(self, mapper: &M) -> Self;
}
pub trait PolicyFieldRef<P: RedactionPolicy> {
type Output;
fn apply_field_ref<M: RedactableMapper>(&self, mapper: &M) -> Self::Output;
}
#[doc(hidden)]
pub trait PolicyFieldRefForFormatting<P: RedactionPolicy> {
type FormattingOutput;
fn apply_field_ref_for_formatting<M: RedactableMapper>(
&self,
mapper: &M,
) -> PolicyFormattingOutput<Self::FormattingOutput>;
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot use generated policy formatting",
note = "custom `PolicyApplicableRef` types used by `SensitiveDisplay` must also implement `redactable::__private::PolicyApplicableRefForFormatting`"
)]
#[doc(hidden)]
pub trait PolicyApplicableRefForFormatting {
fn fmt_policy_display<P>(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
where
P: RedactionPolicy,
P::Kind: RecursivePolicyKind,
Self: PolicyApplicableRef,
<Self as PolicyApplicableRef>::Output: RedactableWithFormatter,
{
self.apply_policy_ref::<P, _>(&PolicyMapper)
.fmt_redacted(formatter)
}
fn fmt_policy_debug<P>(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
where
P: RedactionPolicy,
P::Kind: RecursivePolicyKind,
Self: PolicyApplicableRef,
<Self as PolicyApplicableRef>::Output: std::fmt::Debug,
{
std::fmt::Debug::fmt(&self.apply_policy_ref::<P, _>(&PolicyMapper), formatter)
}
}
#[doc(hidden)]
pub trait PolicyApplicableRefForGeneratedFormatting {
type FormattingOutput;
fn apply_policy_ref_for_generated_formatting<P, M>(
&self,
mapper: &M,
) -> PolicyFormattingOutput<Self::FormattingOutput>
where
P: RedactionPolicy,
P::Kind: RecursivePolicyKind,
M: RedactableMapper;
}
pub trait RecursivePolicyField<P: RedactionPolicy>: Sized {
#[must_use]
fn apply_recursive<M: RedactableMapper>(self, mapper: &M) -> Self;
}
impl<P, T> RecursivePolicyField<P> for T
where
P: RedactionPolicy,
P::Kind: RecursivePolicyKind,
T: PolicyApplicable,
{
fn apply_recursive<M: RedactableMapper>(self, mapper: &M) -> Self {
self.apply_policy::<P, M>(mapper)
}
}
#[doc(hidden)]
pub trait PolicyKindField<P: RedactionPolicy, T: Sized> {
fn apply_kind<M: RedactableMapper>(value: T, mapper: &M) -> T;
}
impl<P, T> PolicyKindField<P, T> for TextPolicyKind
where
P: RedactionPolicy<Kind = TextPolicyKind>,
T: RecursivePolicyField<P>,
{
fn apply_kind<M: RedactableMapper>(value: T, mapper: &M) -> T {
value.apply_recursive(mapper)
}
}
impl<P, T> PolicyKindField<P, T> for SecretPolicyKind
where
P: RedactionPolicy<Kind = SecretPolicyKind>,
T: PolicyApplicable,
{
fn apply_kind<M: RedactableMapper>(value: T, mapper: &M) -> T {
value.apply_policy::<P, M>(mapper)
}
}
impl<P, T> PolicyKindField<P, T> for IpAddressPolicyKind
where
P: RedactionPolicy<Kind = IpAddressPolicyKind>,
T: IpPolicyApplicable<P>,
{
fn apply_kind<M: RedactableMapper>(value: T, mapper: &M) -> T {
value.apply_ip_policy(mapper)
}
}
impl<P, T> PolicyField<P> for T
where
P: RedactionPolicy,
P::Kind: PolicyKindField<P, T>,
{
fn apply_field<M: RedactableMapper>(self, mapper: &M) -> Self {
<P::Kind as PolicyKindField<P, T>>::apply_kind(self, mapper)
}
}
#[doc(hidden)]
pub trait PolicyKindFieldRef<P: RedactionPolicy, T: ?Sized> {
type Output;
fn apply_kind_ref<M: RedactableMapper>(value: &T, mapper: &M) -> Self::Output;
}
#[doc(hidden)]
pub trait PolicyKindFieldRefForFormatting<P: RedactionPolicy, T: ?Sized> {
type FormattingOutput;
fn apply_kind_ref_for_formatting<M: RedactableMapper>(
value: &T,
mapper: &M,
) -> PolicyFormattingOutput<Self::FormattingOutput>;
}
impl<P, T> PolicyKindFieldRef<P, T> for TextPolicyKind
where
P: RedactionPolicy<Kind = TextPolicyKind>,
T: PolicyApplicableRef,
{
type Output = <T as PolicyApplicableRef>::Output;
fn apply_kind_ref<M: RedactableMapper>(value: &T, mapper: &M) -> Self::Output {
value.apply_policy_ref::<P, M>(mapper)
}
}
impl<P, T> PolicyKindFieldRefForFormatting<P, T> for TextPolicyKind
where
P: RedactionPolicy<Kind = TextPolicyKind>,
T: PolicyApplicableRefForGeneratedFormatting,
{
type FormattingOutput = T::FormattingOutput;
fn apply_kind_ref_for_formatting<M: RedactableMapper>(
value: &T,
mapper: &M,
) -> PolicyFormattingOutput<Self::FormattingOutput> {
value.apply_policy_ref_for_generated_formatting::<P, M>(mapper)
}
}
impl<P, T> PolicyKindFieldRef<P, T> for SecretPolicyKind
where
P: RedactionPolicy<Kind = SecretPolicyKind>,
T: PolicyApplicableRef,
{
type Output = <T as PolicyApplicableRef>::Output;
fn apply_kind_ref<M: RedactableMapper>(value: &T, mapper: &M) -> Self::Output {
value.apply_policy_ref::<P, M>(mapper)
}
}
impl<P, T> PolicyKindFieldRefForFormatting<P, T> for SecretPolicyKind
where
P: RedactionPolicy<Kind = SecretPolicyKind>,
T: PolicyApplicableRefForGeneratedFormatting,
{
type FormattingOutput = T::FormattingOutput;
fn apply_kind_ref_for_formatting<M: RedactableMapper>(
value: &T,
mapper: &M,
) -> PolicyFormattingOutput<Self::FormattingOutput> {
value.apply_policy_ref_for_generated_formatting::<P, M>(mapper)
}
}
impl<P, T> PolicyKindFieldRef<P, T> for IpAddressPolicyKind
where
P: RedactionPolicy<Kind = IpAddressPolicyKind>,
T: IpPolicyApplicableRef<P>,
{
type Output = T::Output;
fn apply_kind_ref<M: RedactableMapper>(value: &T, mapper: &M) -> Self::Output {
value.apply_ip_policy_ref(mapper)
}
}
impl<P, T> PolicyKindFieldRefForFormatting<P, T> for IpAddressPolicyKind
where
P: RedactionPolicy<Kind = IpAddressPolicyKind>,
T: IpPolicyApplicableRef<P>,
{
type FormattingOutput = T::Output;
fn apply_kind_ref_for_formatting<M: RedactableMapper>(
value: &T,
mapper: &M,
) -> PolicyFormattingOutput<Self::FormattingOutput> {
value.apply_ip_policy_ref_for_formatting(mapper)
}
}
impl<P, T: ?Sized> PolicyFieldRef<P> for T
where
P: RedactionPolicy,
P::Kind: PolicyKindFieldRef<P, T>,
{
type Output = <P::Kind as PolicyKindFieldRef<P, T>>::Output;
fn apply_field_ref<M: RedactableMapper>(&self, mapper: &M) -> Self::Output {
<P::Kind as PolicyKindFieldRef<P, T>>::apply_kind_ref(self, mapper)
}
}
impl<P, T: ?Sized> PolicyFieldRefForFormatting<P> for T
where
P: RedactionPolicy,
P::Kind: PolicyKindFieldRefForFormatting<P, T>,
{
type FormattingOutput = <P::Kind as PolicyKindFieldRefForFormatting<P, T>>::FormattingOutput;
fn apply_field_ref_for_formatting<M: RedactableMapper>(
&self,
mapper: &M,
) -> PolicyFormattingOutput<Self::FormattingOutput> {
<P::Kind as PolicyKindFieldRefForFormatting<P, T>>::apply_kind_ref_for_formatting(
self, mapper,
)
}
}
macro_rules! impl_secret_scalar {
($($ty:ty),+ $(,)?) => {$ (
impl<P> PolicyKindField<P, $ty> for SecretPolicyKind
where
P: RedactionPolicy<Kind = SecretPolicyKind>,
{
fn apply_kind<M: RedactableMapper>(value: $ty, _mapper: &M) -> $ty {
ScalarRedaction::redact(value)
}
}
impl<P> PolicyKindFieldRef<P, $ty> for SecretPolicyKind
where
P: RedactionPolicy<Kind = SecretPolicyKind>,
{
type Output = $ty;
fn apply_kind_ref<M: RedactableMapper>(value: &$ty, _mapper: &M) -> Self::Output {
ScalarRedaction::redact(*value)
}
}
impl<P> PolicyKindFieldRefForFormatting<P, $ty> for SecretPolicyKind
where
P: RedactionPolicy<Kind = SecretPolicyKind>,
{
type FormattingOutput = $ty;
fn apply_kind_ref_for_formatting<M: RedactableMapper>(
value: &$ty,
_mapper: &M,
) -> PolicyFormattingOutput<$ty> {
PolicyFormattingOutput::Value(ScalarRedaction::redact(*value))
}
}
)+ };
}
impl_secret_scalar!(
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64, bool, char,
);