use std::borrow::Cow;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MaskPolicy {
Fixed {
replacement: String,
},
PreserveEdges {
prefix_chars: usize,
suffix_chars: usize,
replacement: String,
full_mask_below_or_equal: usize,
},
PreserveSuffix {
suffix_chars: usize,
replacement: String,
full_mask_below_or_equal: usize,
},
Empty,
}
impl MaskPolicy {
pub fn fixed(replacement: &str) -> Self {
Self::Fixed {
replacement: replacement.to_string(),
}
}
pub fn preserve_edges(
prefix_chars: usize,
suffix_chars: usize,
replacement: &str,
full_mask_below_or_equal: usize,
) -> Self {
Self::PreserveEdges {
prefix_chars,
suffix_chars,
replacement: replacement.to_string(),
full_mask_below_or_equal,
}
}
pub fn preserve_suffix(
suffix_chars: usize,
replacement: &str,
full_mask_below_or_equal: usize,
) -> Self {
Self::PreserveSuffix {
suffix_chars,
replacement: replacement.to_string(),
full_mask_below_or_equal,
}
}
pub const fn empty() -> Self {
Self::Empty
}
pub fn mask<'a>(&self, value: &'a str) -> Cow<'a, str> {
if value.is_empty() {
return Cow::Borrowed(value);
}
match self {
Self::Fixed { replacement } => Cow::Owned(replacement.clone()),
Self::PreserveEdges {
prefix_chars,
suffix_chars,
replacement,
full_mask_below_or_equal,
} => mask_preserving_edges(
value,
*prefix_chars,
*suffix_chars,
replacement,
*full_mask_below_or_equal,
),
Self::PreserveSuffix {
suffix_chars,
replacement,
full_mask_below_or_equal,
} => {
mask_preserving_suffix(value, *suffix_chars, replacement, *full_mask_below_or_equal)
}
Self::Empty => Cow::Owned(String::new()),
}
}
}
fn mask_preserving_edges<'a>(
value: &str,
prefix_chars: usize,
suffix_chars: usize,
replacement: &str,
full_mask_below_or_equal: usize,
) -> Cow<'a, str> {
let chars = value.chars().collect::<Vec<_>>();
if chars.len() <= full_mask_below_or_equal || chars.len() <= prefix_chars + suffix_chars {
return Cow::Owned(replacement.to_string());
}
let prefix = chars.iter().take(prefix_chars).collect::<String>();
let suffix = chars
.iter()
.skip(chars.len() - suffix_chars)
.collect::<String>();
Cow::Owned(format!("{prefix}{replacement}{suffix}"))
}
fn mask_preserving_suffix<'a>(
value: &str,
suffix_chars: usize,
replacement: &str,
full_mask_below_or_equal: usize,
) -> Cow<'a, str> {
let chars = value.chars().collect::<Vec<_>>();
if chars.len() <= full_mask_below_or_equal || chars.len() <= suffix_chars {
return Cow::Owned(replacement.to_string());
}
let suffix = chars
.iter()
.skip(chars.len() - suffix_chars)
.collect::<String>();
Cow::Owned(format!("{replacement}{suffix}"))
}