summaryrefslogtreecommitdiffstats
path: root/vendor/imara-diff/src/unified_diff.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:35 +0000
commit7e5d7eea9c580ef4b41a765bde624af431942b96 (patch)
tree2c0d9ca12878fc4525650aa4e54d77a81a07cc09 /vendor/imara-diff/src/unified_diff.rs
parentAdding debian version 1.70.0+dfsg1-9. (diff)
downloadrustc-7e5d7eea9c580ef4b41a765bde624af431942b96.tar.xz
rustc-7e5d7eea9c580ef4b41a765bde624af431942b96.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/imara-diff/src/unified_diff.rs')
-rw-r--r--vendor/imara-diff/src/unified_diff.rs136
1 files changed, 136 insertions, 0 deletions
diff --git a/vendor/imara-diff/src/unified_diff.rs b/vendor/imara-diff/src/unified_diff.rs
new file mode 100644
index 000000000..9942d9510
--- /dev/null
+++ b/vendor/imara-diff/src/unified_diff.rs
@@ -0,0 +1,136 @@
+use std::fmt::{Display, Write};
+use std::hash::Hash;
+use std::ops::Range;
+
+use crate::intern::{InternedInput, Interner, Token};
+use crate::Sink;
+
+/// A [`Sink`](crate::sink::Sink) that creates a textual diff
+/// in the format typically output by git or gnu-diff if the `-u` option is used
+pub struct UnifiedDiffBuilder<'a, W, T>
+where
+ W: Write,
+ T: Hash + Eq + Display,
+{
+ before: &'a [Token],
+ after: &'a [Token],
+ interner: &'a Interner<T>,
+
+ pos: u32,
+ before_hunk_start: u32,
+ after_hunk_start: u32,
+ before_hunk_len: u32,
+ after_hunk_len: u32,
+
+ buffer: String,
+ dst: W,
+}
+
+impl<'a, T> UnifiedDiffBuilder<'a, String, T>
+where
+ T: Hash + Eq + Display,
+{
+ /// Create a new `UnifiedDiffBuilder` for the given `input`,
+ /// that will return a [`String`](std::string::String).
+ pub fn new(input: &'a InternedInput<T>) -> Self {
+ Self {
+ before_hunk_start: 0,
+ after_hunk_start: 0,
+ before_hunk_len: 0,
+ after_hunk_len: 0,
+ buffer: String::with_capacity(8),
+ dst: String::new(),
+ interner: &input.interner,
+ before: &input.before,
+ after: &input.after,
+ pos: 0,
+ }
+ }
+}
+
+impl<'a, W, T> UnifiedDiffBuilder<'a, W, T>
+where
+ W: Write,
+ T: Hash + Eq + Display,
+{
+ /// Create a new `UnifiedDiffBuilder` for the given `input`,
+ /// that will writes it output to the provided implementation of [`Write`](std::fmt::Write).
+ pub fn with_writer(input: &'a InternedInput<T>, writer: W) -> Self {
+ Self {
+ before_hunk_start: 0,
+ after_hunk_start: 0,
+ before_hunk_len: 0,
+ after_hunk_len: 0,
+ buffer: String::with_capacity(8),
+ dst: writer,
+ interner: &input.interner,
+ before: &input.before,
+ after: &input.after,
+ pos: 0,
+ }
+ }
+
+ fn print_tokens(&mut self, tokens: &[Token], prefix: char) {
+ for &token in tokens {
+ writeln!(&mut self.buffer, "{prefix}{}", self.interner[token]).unwrap();
+ }
+ }
+
+ fn flush(&mut self) {
+ if self.before_hunk_len == 0 && self.after_hunk_len == 0 {
+ return;
+ }
+
+ let end = (self.pos + 3).min(self.before.len() as u32);
+ self.update_pos(end, end);
+
+ writeln!(
+ &mut self.dst,
+ "@@ -{},{} +{},{} @@",
+ self.before_hunk_start + 1,
+ self.before_hunk_len,
+ self.after_hunk_start + 1,
+ self.after_hunk_len,
+ )
+ .unwrap();
+ write!(&mut self.dst, "{}", &self.buffer).unwrap();
+ self.buffer.clear();
+ self.before_hunk_len = 0;
+ self.after_hunk_len = 0
+ }
+
+ fn update_pos(&mut self, print_to: u32, move_to: u32) {
+ self.print_tokens(&self.before[self.pos as usize..print_to as usize], ' ');
+ let len = print_to - self.pos;
+ self.pos = move_to;
+ self.before_hunk_len += len;
+ self.after_hunk_len += len;
+ }
+}
+
+impl<W, T> Sink for UnifiedDiffBuilder<'_, W, T>
+where
+ W: Write,
+ T: Hash + Eq + Display,
+{
+ type Out = W;
+
+ fn process_change(&mut self, before: Range<u32>, after: Range<u32>) {
+ if before.start - self.pos > 6 {
+ self.flush();
+ self.pos = before.start - 3;
+ self.before_hunk_start = self.pos;
+ self.after_hunk_start = after.start - 3;
+ }
+ self.update_pos(before.start, before.end);
+ self.before_hunk_len += before.end - before.start;
+ self.after_hunk_len += after.end - after.start;
+ self.print_tokens(&self.before[before.start as usize..before.end as usize], '-');
+ self.print_tokens(&self.after[after.start as usize..after.end as usize], '+');
+ }
+
+ fn finish(mut self) -> Self::Out {
+ self.flush();
+ self.dst
+ }
+}