use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LineType {
Added,
Removed,
Context,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HunkLine {
pub line_type: LineType,
pub old_line: Option<usize>,
pub new_line: Option<usize>,
pub content: String,
}
impl HunkLine {
pub fn added(new_line: usize, content: String) -> Self {
Self {
line_type: LineType::Added,
old_line: None,
new_line: Some(new_line),
content,
}
}
pub fn removed(old_line: usize, content: String) -> Self {
Self {
line_type: LineType::Removed,
old_line: Some(old_line),
new_line: None,
content,
}
}
pub fn context(old_line: usize, new_line: usize, content: String) -> Self {
Self {
line_type: LineType::Context,
old_line: Some(old_line),
new_line: Some(new_line),
content,
}
}
pub fn is_added(&self) -> bool {
matches!(self.line_type, LineType::Added)
}
pub fn is_removed(&self) -> bool {
matches!(self.line_type, LineType::Removed)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Hunk {
pub old_start: usize,
pub old_count: usize,
pub new_start: usize,
pub new_count: usize,
pub lines: Vec<HunkLine>,
}
impl Hunk {
pub fn new(old_start: usize, old_count: usize, new_start: usize, new_count: usize) -> Self {
Self {
old_start,
old_count,
new_start,
new_count,
lines: Vec::new(),
}
}
pub fn added_count(&self) -> usize {
self.lines.iter().filter(|l| l.is_added()).count()
}
pub fn removed_count(&self) -> usize {
self.lines.iter().filter(|l| l.is_removed()).count()
}
pub fn added_lines(&self) -> Vec<usize> {
self.lines
.iter()
.filter_map(|l| if l.is_added() { l.new_line } else { None })
.collect()
}
pub fn removed_lines(&self) -> Vec<usize> {
self.lines
.iter()
.filter_map(|l| if l.is_removed() { l.old_line } else { None })
.collect()
}
}