@@ -272,34 +272,7 @@ fn normalize_value_to_unordered_redactions(
272
272
* act = normalize_str_to_unordered_redactions ( act, exp, substitutions) ;
273
273
}
274
274
( Array ( act) , Array ( exp) ) => {
275
- let mut actual_values = std:: mem:: take ( act) ;
276
- let mut expected_values = exp. clone ( ) ;
277
- let mut elided = false ;
278
- expected_values. retain ( |expected_value| {
279
- let mut matched = false ;
280
- if expected_value == VALUE_WILDCARD {
281
- matched = true ;
282
- elided = true ;
283
- } else {
284
- actual_values. retain ( |actual_value| {
285
- if !matched && actual_value == expected_value {
286
- matched = true ;
287
- false
288
- } else {
289
- true
290
- }
291
- } ) ;
292
- }
293
- if matched {
294
- act. push ( expected_value. clone ( ) ) ;
295
- }
296
- !matched
297
- } ) ;
298
- if !elided {
299
- for actual_value in actual_values {
300
- act. push ( actual_value) ;
301
- }
302
- }
275
+ * act = normalize_array_to_unordered_redactions ( act, exp, substitutions) ;
303
276
}
304
277
( Object ( act) , Object ( exp) ) => {
305
278
let has_key_wildcard =
@@ -324,6 +297,55 @@ fn normalize_value_to_unordered_redactions(
324
297
}
325
298
}
326
299
300
+ #[ cfg( feature = "structured-data" ) ]
301
+ fn normalize_array_to_unordered_redactions (
302
+ actual : & [ serde_json:: Value ] ,
303
+ expected : & [ serde_json:: Value ] ,
304
+ substitutions : & Redactions ,
305
+ ) -> Vec < serde_json:: Value > {
306
+ if actual == expected {
307
+ return actual. to_owned ( ) ;
308
+ }
309
+
310
+ let mut normalized: Vec < serde_json:: Value > = Vec :: new ( ) ;
311
+ let mut actual_values = actual. to_owned ( ) ;
312
+ let mut expected_values = expected. to_owned ( ) ;
313
+ let mut elided = false ;
314
+ expected_values. retain ( |expected_value| {
315
+ let mut matched = false ;
316
+ if expected_value == VALUE_WILDCARD {
317
+ matched = true ;
318
+ elided = true ;
319
+ } else {
320
+ actual_values. retain ( |actual_value| {
321
+ let mut normalized_actual_value = actual_value. clone ( ) ;
322
+ normalize_value_to_unordered_redactions (
323
+ & mut normalized_actual_value,
324
+ expected_value,
325
+ substitutions,
326
+ ) ;
327
+ if !matched && normalized_actual_value == * expected_value {
328
+ matched = true ;
329
+ false
330
+ } else {
331
+ true
332
+ }
333
+ } ) ;
334
+ }
335
+ if matched {
336
+ normalized. push ( expected_value. clone ( ) ) ;
337
+ }
338
+ !matched
339
+ } ) ;
340
+ if !elided {
341
+ for actual_value in actual_values {
342
+ normalized. push ( actual_value) ;
343
+ }
344
+ }
345
+
346
+ normalized
347
+ }
348
+
327
349
fn normalize_str_to_unordered_redactions (
328
350
actual : & str ,
329
351
expected : & str ,
@@ -454,120 +476,124 @@ fn normalize_value_to_redactions(
454
476
455
477
#[ cfg( feature = "structured-data" ) ]
456
478
fn normalize_array_to_redactions (
457
- input : & [ serde_json:: Value ] ,
458
- pattern : & [ serde_json:: Value ] ,
479
+ actual : & [ serde_json:: Value ] ,
480
+ expected : & [ serde_json:: Value ] ,
459
481
redactions : & Redactions ,
460
482
) -> Vec < serde_json:: Value > {
461
- if input == pattern {
462
- return input . to_vec ( ) ;
483
+ if actual == expected {
484
+ return actual . to_vec ( ) ;
463
485
}
464
486
465
487
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 {
488
+ let mut actual_index = 0 ;
489
+ let mut expected = expected . iter ( ) . peekable ( ) ;
490
+ while let Some ( expected_elem ) = expected . next ( ) {
491
+ if expected_elem == VALUE_WILDCARD {
492
+ let Some ( next_expected_elem ) = expected . peek ( ) else {
471
493
// Stop as elide consumes to end
472
- normalized. push ( pattern_elem . clone ( ) ) ;
473
- input_index = input . len ( ) ;
494
+ normalized. push ( expected_elem . clone ( ) ) ;
495
+ actual_index = actual . len ( ) ;
474
496
break ;
475
497
} ;
476
- let Some ( index_offset) = input[ input_index..] . iter ( ) . position ( |next_input_elem| {
477
- let mut next_input_elem = next_input_elem. clone ( ) ;
478
- normalize_value_to_redactions ( & mut next_input_elem, next_pattern_elem, redactions) ;
479
- next_input_elem == * * next_pattern_elem
498
+ let Some ( index_offset) = actual[ actual_index..] . iter ( ) . position ( |next_actual_elem| {
499
+ let mut next_actual_elem = next_actual_elem. clone ( ) ;
500
+ normalize_value_to_redactions (
501
+ & mut next_actual_elem,
502
+ next_expected_elem,
503
+ redactions,
504
+ ) ;
505
+ next_actual_elem == * * next_expected_elem
480
506
} ) else {
481
507
// Give up as we can't find where the elide ends
482
508
break ;
483
509
} ;
484
- normalized. push ( pattern_elem . clone ( ) ) ;
485
- input_index += index_offset;
510
+ normalized. push ( expected_elem . clone ( ) ) ;
511
+ actual_index += index_offset;
486
512
} else {
487
- let Some ( input_elem ) = input . get ( input_index ) else {
513
+ let Some ( actual_elem ) = actual . get ( actual_index ) else {
488
514
// Give up as we have no more content to check
489
515
break ;
490
516
} ;
491
517
492
- input_index += 1 ;
493
- let mut normalized_elem = input_elem . clone ( ) ;
494
- normalize_value_to_redactions ( & mut normalized_elem, pattern_elem , redactions) ;
518
+ actual_index += 1 ;
519
+ let mut normalized_elem = actual_elem . clone ( ) ;
520
+ normalize_value_to_redactions ( & mut normalized_elem, expected_elem , redactions) ;
495
521
normalized. push ( normalized_elem) ;
496
522
}
497
523
}
498
524
499
- normalized. extend ( input [ input_index ..] . iter ( ) . cloned ( ) ) ;
525
+ normalized. extend ( actual [ actual_index ..] . iter ( ) . cloned ( ) ) ;
500
526
normalized
501
527
}
502
528
503
- fn normalize_str_to_redactions ( input : & str , pattern : & str , redactions : & Redactions ) -> String {
504
- if input == pattern {
505
- return input . to_owned ( ) ;
529
+ fn normalize_str_to_redactions ( actual : & str , expected : & str , redactions : & Redactions ) -> String {
530
+ if actual == expected {
531
+ return actual . to_owned ( ) ;
506
532
}
507
533
508
534
let mut normalized: Vec < & str > = Vec :: new ( ) ;
509
- let mut input_index = 0 ;
510
- let input_lines : Vec < _ > = crate :: utils:: LinesWithTerminator :: new ( input ) . collect ( ) ;
511
- let mut pattern_lines = crate :: utils:: LinesWithTerminator :: new ( pattern ) . peekable ( ) ;
512
- while let Some ( pattern_line ) = pattern_lines . next ( ) {
513
- if is_line_elide ( pattern_line ) {
514
- let Some ( next_pattern_line ) = pattern_lines . peek ( ) else {
535
+ let mut actual_index = 0 ;
536
+ let actual_lines : Vec < _ > = crate :: utils:: LinesWithTerminator :: new ( actual ) . collect ( ) ;
537
+ let mut expected_lines = crate :: utils:: LinesWithTerminator :: new ( expected ) . peekable ( ) ;
538
+ while let Some ( expected_line ) = expected_lines . next ( ) {
539
+ if is_line_elide ( expected_line ) {
540
+ let Some ( next_expected_line ) = expected_lines . peek ( ) else {
515
541
// Stop as elide consumes to end
516
- normalized. push ( pattern_line ) ;
517
- input_index = input_lines . len ( ) ;
542
+ normalized. push ( expected_line ) ;
543
+ actual_index = actual_lines . len ( ) ;
518
544
break ;
519
545
} ;
520
546
let Some ( index_offset) =
521
- input_lines [ input_index ..]
547
+ actual_lines [ actual_index ..]
522
548
. iter ( )
523
- . position ( |next_input_line | {
524
- line_matches ( next_input_line , next_pattern_line , redactions)
549
+ . position ( |next_actual_line | {
550
+ line_matches ( next_actual_line , next_expected_line , redactions)
525
551
} )
526
552
else {
527
553
// Give up as we can't find where the elide ends
528
554
break ;
529
555
} ;
530
- normalized. push ( pattern_line ) ;
531
- input_index += index_offset;
556
+ normalized. push ( expected_line ) ;
557
+ actual_index += index_offset;
532
558
} else {
533
- let Some ( input_line ) = input_lines . get ( input_index ) else {
559
+ let Some ( actual_line ) = actual_lines . get ( actual_index ) else {
534
560
// Give up as we have no more content to check
535
561
break ;
536
562
} ;
537
563
538
- if line_matches ( input_line , pattern_line , redactions) {
539
- input_index += 1 ;
540
- normalized. push ( pattern_line ) ;
564
+ if line_matches ( actual_line , expected_line , redactions) {
565
+ actual_index += 1 ;
566
+ normalized. push ( expected_line ) ;
541
567
} else {
542
568
// Skip this line and keep processing
543
- input_index += 1 ;
544
- normalized. push ( input_line ) ;
569
+ actual_index += 1 ;
570
+ normalized. push ( actual_line ) ;
545
571
}
546
572
}
547
573
}
548
574
549
- normalized. extend ( input_lines [ input_index ..] . iter ( ) . copied ( ) ) ;
575
+ normalized. extend ( actual_lines [ actual_index ..] . iter ( ) . copied ( ) ) ;
550
576
normalized. join ( "" )
551
577
}
552
578
553
579
fn is_line_elide ( line : & str ) -> bool {
554
580
line == "...\n " || line == "..."
555
581
}
556
582
557
- fn line_matches ( mut input : & str , pattern : & str , redactions : & Redactions ) -> bool {
558
- if input == pattern {
583
+ fn line_matches ( mut actual : & str , expected : & str , redactions : & Redactions ) -> bool {
584
+ if actual == expected {
559
585
return true ;
560
586
}
561
587
562
- let pattern = redactions. clear ( pattern ) ;
563
- let mut sections = pattern . split ( "[..]" ) . peekable ( ) ;
588
+ let expected = redactions. clear ( expected ) ;
589
+ let mut sections = expected . split ( "[..]" ) . peekable ( ) ;
564
590
while let Some ( section) = sections. next ( ) {
565
- if let Some ( remainder) = input . strip_prefix ( section) {
591
+ if let Some ( remainder) = actual . strip_prefix ( section) {
566
592
if let Some ( next_section) = sections. peek ( ) {
567
593
if next_section. is_empty ( ) {
568
- input = "" ;
594
+ actual = "" ;
569
595
} else if let Some ( restart_index) = remainder. find ( next_section) {
570
- input = & remainder[ restart_index..] ;
596
+ actual = & remainder[ restart_index..] ;
571
597
}
572
598
} else {
573
599
return remainder. is_empty ( ) ;
0 commit comments