diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/imara-diff/src/unified_diff.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.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.rs | 136 |
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 + } +} |