use std::convert::Infallible; use crate::{group_diff_ops, DiffHook, DiffOp}; /// A [`DiffHook`] that captures all diff operations. #[derive(Default, Clone)] pub struct Capture(Vec); impl Capture { /// Creates a new capture hook. pub fn new() -> Capture { Capture::default() } /// Converts the capture hook into a vector of ops. pub fn into_ops(self) -> Vec { self.0 } /// Isolate change clusters by eliminating ranges with no changes. /// /// This is equivalent to calling [`group_diff_ops`] on [`Capture::into_ops`]. pub fn into_grouped_ops(self, n: usize) -> Vec> { group_diff_ops(self.into_ops(), n) } /// Accesses the captured operations. pub fn ops(&self) -> &[DiffOp] { &self.0 } } impl DiffHook for Capture { type Error = Infallible; fn equal(&mut self, old_index: usize, new_index: usize, len: usize) -> Result<(), Self::Error> { self.0.push(DiffOp::Equal { old_index, new_index, len, }); Ok(()) } fn delete( &mut self, old_index: usize, old_len: usize, new_index: usize, ) -> Result<(), Self::Error> { self.0.push(DiffOp::Delete { old_index, old_len, new_index, }); Ok(()) } fn insert( &mut self, old_index: usize, new_index: usize, new_len: usize, ) -> Result<(), Self::Error> { self.0.push(DiffOp::Insert { old_index, new_index, new_len, }); Ok(()) } fn replace( &mut self, old_index: usize, old_len: usize, new_index: usize, new_len: usize, ) -> Result<(), Self::Error> { self.0.push(DiffOp::Replace { old_index, old_len, new_index, new_len, }); Ok(()) } } #[test] fn test_capture_hook_grouping() { use crate::algorithms::{myers, Replace}; let rng = (1..100).collect::>(); let mut rng_new = rng.clone(); rng_new[10] = 1000; rng_new[13] = 1000; rng_new[16] = 1000; rng_new[34] = 1000; let mut d = Replace::new(Capture::new()); myers::diff_slices(&mut d, &rng, &rng_new).unwrap(); let ops = d.into_inner().into_grouped_ops(3); let tags = ops .iter() .map(|group| group.iter().map(|x| x.as_tag_tuple()).collect::>()) .collect::>(); insta::assert_debug_snapshot!(ops); insta::assert_debug_snapshot!(tags); }