/rust/registry/src/index.crates.io-1949cf8c6b5b557f/imara-diff-0.1.8/src/sink.rs
Line | Count | Source |
1 | | use std::ops::Range; |
2 | | |
3 | | /// Trait for processing the edit-scripts computed with [`diff`](crate::diff) |
4 | | pub trait Sink: Sized { |
5 | | type Out; |
6 | | |
7 | | /// This method is called whenever a diff [`algorithm`](crate::Algorithm) |
8 | | /// finds a change between the two processed input files. |
9 | | /// A change is a continuous subsequence of [tokens](crate::intern::Token) `before` that needs |
10 | | /// to be replaced by a different continuous subsequence of tokens `after` to construct the second file from the first. |
11 | | /// |
12 | | /// These token subsequences are passed to this function in in ** strictly monotonically increasing order**. |
13 | | /// That means that for two subsequent calls `process_change(before1, after1)` and `process_change(before2, after2)` |
14 | | /// the following always holds: |
15 | | /// |
16 | | /// ``` no_compile |
17 | | /// assert!(before1.end < before2.start); |
18 | | /// assert!(after1.end < after2.start); |
19 | | /// ``` |
20 | | /// |
21 | | /// # Parameters |
22 | | /// - **`before`** - the **position** of the removed token subsequence in the orignal file. |
23 | | /// - **`after`** - the **position** of the inserted token subsequence in the destination file. |
24 | | /// |
25 | | /// # Notes |
26 | | //// |
27 | | /// A `Sink` has no function to indicate that a section of a file remains unchanged. |
28 | | /// However due to the monotonically increasing calls, implementations can easily determine |
29 | | /// which subsequences remain unchanged by saving `before.end`/`after.end`. |
30 | | /// The range between `before.start`/`after.end` and the previous `before.end`/`after.end` |
31 | | /// is always unchanged. |
32 | | fn process_change(&mut self, before: Range<u32>, after: Range<u32>); |
33 | | |
34 | | /// This function is called after all calls to `process_change` are complete |
35 | | /// to obtain the final diff result |
36 | | fn finish(self) -> Self::Out; |
37 | | |
38 | | /// Utility method that constructs a [`Counter`] that tracks the total number |
39 | | /// of inserted and removed tokens in the changes passed to [`process_change`](crate::Sink::process_change). |
40 | 0 | fn with_counter(self) -> Counter<Self> { |
41 | 0 | Counter::new(self) |
42 | 0 | } |
43 | | } |
44 | | |
45 | | impl<T: FnMut(Range<u32>, Range<u32>)> Sink for T { |
46 | | type Out = (); |
47 | | |
48 | 0 | fn process_change(&mut self, before: Range<u32>, after: Range<u32>) { |
49 | 0 | self(before, after) |
50 | 0 | } Unexecuted instantiation: <<imara_diff::histogram::Histogram>::run<gix_merge::blob::builtin_driver::text::utils::CollectHunks>::{closure#0} as imara_diff::sink::Sink>::process_changeUnexecuted instantiation: <_ as imara_diff::sink::Sink>::process_change |
51 | | |
52 | 0 | fn finish(self) -> Self::Out {}Unexecuted instantiation: <<imara_diff::histogram::Histogram>::run<gix_merge::blob::builtin_driver::text::utils::CollectHunks>::{closure#0} as imara_diff::sink::Sink>::finishUnexecuted instantiation: <_ as imara_diff::sink::Sink>::finish |
53 | | } |
54 | | |
55 | | impl Sink for () { |
56 | | type Out = (); |
57 | 0 | fn process_change(&mut self, _before: Range<u32>, _after: Range<u32>) {} |
58 | 0 | fn finish(self) -> Self::Out {} |
59 | | } |
60 | | |
61 | | /// A [`Sink`] which wraps a different sink |
62 | | /// and counts the number of `removed` and `inserted` [tokens](crate::intern::Token). |
63 | | pub struct Counter<T> { |
64 | | /// Total number of recorded inserted [`tokens`](crate::intern::Token). |
65 | | /// Computed by summing the lengths of the `after` subsequences pass to [`process_change`](crate::Sink::process_change). |
66 | | pub removals: u32, |
67 | | /// Total number of recorded inserted [`tokens`](crate::intern::Token). |
68 | | /// Computed by summing the lengths of the `after` subsequences pass to [`process_change`](crate::Sink::process_change). |
69 | | pub insertions: u32, |
70 | | /// The [`Sink`] for which the counter records [`tokens`](crate::intern::Token). |
71 | | /// All calls to [`process_change`](crate::Sink::process_change) are forwarded to the `sink` by the counter. |
72 | | /// After [`finish`](crate::Sink::finish) is called, this field contains the output returned by the [`finish`](crate::Sink::finish) |
73 | | /// method of the wrapped [`Sink`]. |
74 | | pub wrapped: T, |
75 | | } |
76 | | |
77 | | impl<S: Sink> Counter<S> { |
78 | 0 | pub fn new(sink: S) -> Self { |
79 | 0 | Self { |
80 | 0 | insertions: 0, |
81 | 0 | removals: 0, |
82 | 0 | wrapped: sink, |
83 | 0 | } |
84 | 0 | } |
85 | | } |
86 | | |
87 | | impl<S: Sink> Sink for Counter<S> { |
88 | | type Out = Counter<S::Out>; |
89 | 0 | fn process_change(&mut self, before: Range<u32>, after: Range<u32>) { |
90 | 0 | self.removals += before.end - before.start; |
91 | 0 | self.insertions += after.end - after.start; |
92 | 0 | self.wrapped.process_change(before, after) |
93 | 0 | } |
94 | | |
95 | 0 | fn finish(self) -> Self::Out { |
96 | 0 | Counter { |
97 | 0 | removals: self.removals, |
98 | 0 | insertions: self.insertions, |
99 | 0 | wrapped: self.wrapped.finish(), |
100 | 0 | } |
101 | 0 | } |
102 | | } |
103 | | |
104 | | impl<T> Counter<T> { |
105 | 0 | pub fn total(&self) -> usize { |
106 | 0 | self.insertions as usize + self.removals as usize |
107 | 0 | } |
108 | | } |
109 | | |
110 | | impl Default for Counter<()> { |
111 | 0 | fn default() -> Self { |
112 | 0 | Counter::new(()) |
113 | 0 | } |
114 | | } |