use std::borrow::Cow;
use super::MaskPolicy;
use super::MaskingPolicyBuilder;
use crate::policy::PolicyError;
use crate::policy::PolicyLocation;
use crate::policy::Sensitivity;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MaskingPolicy {
low: MaskPolicy,
medium: MaskPolicy,
high: MaskPolicy,
secret: MaskPolicy,
}
impl MaskingPolicy {
#[must_use]
#[inline(always)]
pub fn builder() -> MaskingPolicyBuilder {
MaskingPolicyBuilder::default()
}
#[must_use]
#[inline(always)]
pub(crate) fn builder_from(base: &Self) -> MaskingPolicyBuilder {
MaskingPolicyBuilder::from_policy(base)
}
#[must_use]
#[inline(always)]
pub(super) fn from_parts(low: MaskPolicy, medium: MaskPolicy, high: MaskPolicy, secret: MaskPolicy) -> Self {
Self {
low,
medium,
high,
secret,
}
}
#[must_use]
#[inline(always)]
pub const fn for_level(&self, level: Sensitivity) -> &MaskPolicy {
match level {
Sensitivity::Low => &self.low,
Sensitivity::Medium => &self.medium,
Sensitivity::High => &self.high,
Sensitivity::Secret => &self.secret,
}
}
#[must_use]
#[inline(always)]
pub fn mask<'a>(&self, level: Sensitivity, value: &'a str) -> Cow<'a, str> {
self.for_level(level).mask(value)
}
#[must_use]
#[inline(always)]
pub fn mask_opaque(&self, level: Sensitivity) -> &str {
self.for_level(level).opaque_mask()
}
#[must_use]
#[inline(always)]
#[cfg(feature = "http")]
pub(crate) fn mask_bounded<'a>(&self, level: Sensitivity, value: &'a str, max_bytes: usize) -> Cow<'a, str> {
self.for_level(level).mask_bounded(value, max_bytes)
}
#[must_use]
#[inline(always)]
pub(crate) fn mask_bounded_with_truncation<'a>(
&self,
level: Sensitivity,
value: &'a str,
max_bytes: usize,
) -> (Cow<'a, str>, bool) {
self.for_level(level).mask_bounded_with_truncation(value, max_bytes)
}
#[must_use]
#[inline(always)]
pub(crate) fn mask_opaque_bounded(&self, level: Sensitivity, max_bytes: usize) -> String {
self.for_level(level).opaque_mask_bounded(max_bytes)
}
pub(crate) fn validate(&self, location: PolicyLocation) -> Result<(), PolicyError> {
for level in [
Sensitivity::Low,
Sensitivity::Medium,
Sensitivity::High,
Sensitivity::Secret,
] {
if matches!(
self.for_level(level),
MaskPolicy::Fixed { replacement } if replacement.is_empty()
) {
return Err(PolicyError::EmptyFixedReplacement { location, level });
}
}
Ok(())
}
}
impl Default for MaskingPolicy {
#[inline(always)]
fn default() -> Self {
Self::builder().build()
}
}