From adae0fe3bb8f96adcab91f72a50e0aa11b4d41e8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 19 Apr 2024 16:48:21 -0500 Subject: [PATCH] fix(sub)!: Abstract away substitution values This will give us more implementation flexibility Cherry pick 286ac5dd22d99623929d78aa5c426fdd1637c3ce (#281) --- crates/snapbox/src/filter/mod.rs | 1 + crates/snapbox/src/filter/redactions.rs | 74 ++++++++++++++++++------- crates/snapbox/src/lib.rs | 1 + 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/crates/snapbox/src/filter/mod.rs b/crates/snapbox/src/filter/mod.rs index 7d58818a..c33e7746 100644 --- a/crates/snapbox/src/filter/mod.rs +++ b/crates/snapbox/src/filter/mod.rs @@ -11,6 +11,7 @@ mod test; use crate::data::DataInner; use crate::Data; +pub use redactions::RedactedValue; pub use redactions::Redactions; pub trait Filter { diff --git a/crates/snapbox/src/filter/redactions.rs b/crates/snapbox/src/filter/redactions.rs index 80078d59..d6ded213 100644 --- a/crates/snapbox/src/filter/redactions.rs +++ b/crates/snapbox/src/filter/redactions.rs @@ -7,8 +7,8 @@ use std::borrow::Cow; /// - `[..]`: match multiple characters within a line #[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct Redactions { - vars: std::collections::BTreeMap<&'static str, std::collections::BTreeSet>>, - unused: std::collections::BTreeSet<&'static str>, + vars: std::collections::BTreeMap<&'static str, std::collections::BTreeSet>, + unused: std::collections::BTreeSet, } impl Redactions { @@ -35,18 +35,14 @@ impl Redactions { pub fn insert( &mut self, placeholder: &'static str, - value: impl Into>, + value: impl Into, ) -> crate::assert::Result<()> { let placeholder = validate_placeholder(placeholder)?; let value = value.into(); - if value.is_empty() { - self.unused.insert(placeholder); + if let Some(inner) = value.inner { + self.vars.entry(placeholder).or_default().insert(inner); } else { - #[allow(deprecated)] - self.vars - .entry(placeholder) - .or_default() - .insert(crate::utils::normalize_text(value.as_ref()).into()); + self.unused.insert(RedactedValueInner::Str(placeholder)); } Ok(()) } @@ -56,7 +52,7 @@ impl Redactions { /// placeholders must be enclosed in `[` and `]`. pub fn extend( &mut self, - vars: impl IntoIterator>)>, + vars: impl IntoIterator)>, ) -> crate::assert::Result<()> { for (placeholder, value) in vars { self.insert(placeholder, value)?; @@ -89,9 +85,9 @@ impl Redactions { let mut input = input.to_owned(); replace_many( &mut input, - self.vars.iter().flat_map(|(var, replaces)| { - replaces.iter().map(|replace| (replace.as_ref(), *var)) - }), + self.vars + .iter() + .flat_map(|(var, replaces)| replaces.iter().map(|replace| (replace, *var))), ); Cow::Owned(input) } @@ -99,7 +95,7 @@ impl Redactions { fn clear<'v>(&self, pattern: &'v str) -> Cow<'v, str> { if !self.unused.is_empty() && pattern.contains('[') { let mut pattern = pattern.to_owned(); - replace_many(&mut pattern, self.unused.iter().map(|var| (*var, ""))); + replace_many(&mut pattern, self.unused.iter().map(|var| (var, ""))); Cow::Owned(pattern) } else { Cow::Borrowed(pattern) @@ -107,16 +103,56 @@ impl Redactions { } } +#[derive(Clone)] +pub struct RedactedValue { + inner: Option, +} + +#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] +enum RedactedValueInner { + Str(&'static str), + String(String), +} + +impl RedactedValueInner { + fn find_in(&self, buffer: &str) -> Option> { + match self { + Self::Str(s) => buffer.find(s).map(|offset| offset..(offset + s.len())), + Self::String(s) => buffer.find(s).map(|offset| offset..(offset + s.len())), + } + } +} + +impl From for RedactedValue +where + C: Into>, +{ + fn from(inner: C) -> Self { + let inner = inner.into(); + if inner.is_empty() { + Self { inner: None } + } else { + #[allow(deprecated)] + Self { + inner: Some(RedactedValueInner::String(crate::utils::normalize_text( + &inner, + ))), + } + } + } +} + +/// Replacements is `(from, to)` fn replace_many<'a>( buffer: &mut String, - replacements: impl IntoIterator, + replacements: impl IntoIterator, ) { for (var, replace) in replacements { let mut index = 0; - while let Some(offset) = buffer[index..].find(var) { - let old_range = (index + offset)..(index + offset + var.len()); + while let Some(offset) = var.find_in(&buffer[index..]) { + let old_range = (index + offset.start)..(index + offset.end); buffer.replace_range(old_range, replace); - index += offset + replace.len(); + index += offset.start + replace.len(); } } } diff --git a/crates/snapbox/src/lib.rs b/crates/snapbox/src/lib.rs index be89e30e..6724046d 100644 --- a/crates/snapbox/src/lib.rs +++ b/crates/snapbox/src/lib.rs @@ -114,6 +114,7 @@ pub use assert::Action; pub use assert::Assert; pub use data::Data; pub use data::ToDebug; +pub use filter::RedactedValue; pub use filter::Redactions; #[doc(hidden)] pub use snapbox_macros::debug;