Skip to content

Commit b71f8d0

Browse files
committed
refactor(filter): Rewrite Array normalization to match str
1 parent 140a6a4 commit b71f8d0

File tree

1 file changed

+48
-32
lines changed

1 file changed

+48
-32
lines changed

crates/snapbox/src/filter/pattern.rs

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -431,38 +431,7 @@ fn normalize_value_to_redactions(
431431
*act = normalize_str_to_redactions(act, exp, substitutions);
432432
}
433433
(Array(act), Array(exp)) => {
434-
let mut sections = exp.split(|e| e == VALUE_WILDCARD).peekable();
435-
let mut processed = 0;
436-
while let Some(expected_subset) = sections.next() {
437-
// Process all values in the current section
438-
if !expected_subset.is_empty() {
439-
let actual_subset = &mut act[processed..processed + expected_subset.len()];
440-
for (a, e) in actual_subset.iter_mut().zip(expected_subset) {
441-
normalize_value_to_redactions(a, e, substitutions);
442-
}
443-
processed += expected_subset.len();
444-
}
445-
446-
if let Some(next_section) = sections.peek() {
447-
// If the next section has nothing in it, replace from processed to end with
448-
// a single "{...}"
449-
if next_section.is_empty() {
450-
act.splice(processed.., vec![String(VALUE_WILDCARD.to_owned())]);
451-
processed += 1;
452-
} else {
453-
let first = next_section.first().unwrap();
454-
// Replace everything up until the value we are looking for with
455-
// a single "{...}".
456-
if let Some(index) = act.iter().position(|v| v == first) {
457-
act.splice(processed..index, vec![String(VALUE_WILDCARD.to_owned())]);
458-
processed += 1;
459-
} else {
460-
// If we cannot find the value we are looking for return early
461-
break;
462-
}
463-
}
464-
}
465-
}
434+
*act = normalize_array_to_redactions(act, exp, substitutions);
466435
}
467436
(Object(act), Object(exp)) => {
468437
let has_key_wildcard =
@@ -483,6 +452,53 @@ fn normalize_value_to_redactions(
483452
}
484453
}
485454

455+
#[cfg(feature = "structured-data")]
456+
fn normalize_array_to_redactions(
457+
input: &[serde_json::Value],
458+
pattern: &[serde_json::Value],
459+
redactions: &Redactions,
460+
) -> Vec<serde_json::Value> {
461+
if input == pattern {
462+
return input.to_vec();
463+
}
464+
465+
let mut normalized: Vec<serde_json::Value> = Vec::new();
466+
let mut input_index = 0;
467+
let mut pattern = pattern.iter().peekable();
468+
while let Some(pattern_elem) = pattern.next() {
469+
if pattern_elem == VALUE_WILDCARD {
470+
let Some(next_pattern_elem) = pattern.peek() else {
471+
// Stop as elide consumes to end
472+
normalized.push(pattern_elem.clone());
473+
input_index = input.len();
474+
break;
475+
};
476+
let Some(index_offset) = input[input_index..]
477+
.iter()
478+
.position(|next_input_elem| next_input_elem == *next_pattern_elem)
479+
else {
480+
// Give up as we can't find where the elide ends
481+
break;
482+
};
483+
normalized.push(pattern_elem.clone());
484+
input_index += index_offset;
485+
} else {
486+
let Some(input_elem) = input.get(input_index) else {
487+
// Give up as we have no more content to check
488+
break;
489+
};
490+
491+
input_index += 1;
492+
let mut normalized_elem = input_elem.clone();
493+
normalize_value_to_redactions(&mut normalized_elem, pattern_elem, redactions);
494+
normalized.push(normalized_elem);
495+
}
496+
}
497+
498+
normalized.extend(input[input_index..].iter().cloned());
499+
normalized
500+
}
501+
486502
fn normalize_str_to_redactions(input: &str, pattern: &str, redactions: &Redactions) -> String {
487503
if input == pattern {
488504
return input.to_owned();

0 commit comments

Comments
 (0)