use std::borrow::Cow;
use crate::{
MaskingPolicy,
RedactedText,
RedactionRules,
Sensitivity,
policy::ResolvedField,
};
pub(in crate::http) struct FieldRedactor<'a> {
base_rules: &'a RedactionRules,
context_rules: &'a RedactionRules,
masking: &'a MaskingPolicy,
}
impl<'a> FieldRedactor<'a> {
pub(in crate::http) const fn new(
base_rules: &'a RedactionRules,
context_rules: &'a RedactionRules,
masking: &'a MaskingPolicy,
) -> Self {
Self {
base_rules,
context_rules,
masking,
}
}
pub(in crate::http) fn redact_bounded<'value>(
&self,
field: &str,
value: &'value str,
max_bytes: usize,
) -> RedactedText<'value> {
self.redact_bounded_if_sensitive(field, value, max_bytes)
.unwrap_or_else(|| RedactedText::new(Cow::Borrowed(value)))
}
pub(in crate::http) fn redact_bounded_if_sensitive<'value>(
&self,
field: &str,
value: &'value str,
max_bytes: usize,
) -> Option<RedactedText<'value>> {
let resolved = stronger(
self.base_rules.resolve_field(field),
self.context_rules.resolve_field(field),
);
match resolved {
ResolvedField::Sensitive { sensitivity } => {
Some(RedactedText::new(self.masking.mask_bounded(
sensitivity,
value,
max_bytes,
)))
}
ResolvedField::PassThrough => None,
}
}
pub(in crate::http) fn mask_bounded<'value>(
&self,
level: Sensitivity,
value: &'value str,
max_bytes: usize,
) -> Cow<'value, str> {
self.masking.mask_bounded(level, value, max_bytes)
}
pub(in crate::http) const fn base_rules(&self) -> &'a RedactionRules {
self.base_rules
}
pub(in crate::http) const fn context_rules(&self) -> &'a RedactionRules {
self.context_rules
}
pub(in crate::http) const fn masking(&self) -> &'a MaskingPolicy {
self.masking
}
}
fn stronger(base: ResolvedField, context: ResolvedField) -> ResolvedField {
match (base, context) {
(
ResolvedField::Sensitive { sensitivity: base },
ResolvedField::Sensitive {
sensitivity: context,
},
) => ResolvedField::Sensitive {
sensitivity: base.max(context),
},
(
ResolvedField::Sensitive { sensitivity },
ResolvedField::PassThrough,
)
| (
ResolvedField::PassThrough,
ResolvedField::Sensitive { sensitivity },
) => ResolvedField::Sensitive { sensitivity },
(ResolvedField::PassThrough, ResolvedField::PassThrough) => {
ResolvedField::PassThrough
}
}
}