1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum ChangeKind {
8 Insert,
10 Delete,
12 Replace,
14 Equal,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20pub struct ChangeSpan {
21 pub kind: ChangeKind,
23 pub text: String,
25 pub new_text: Option<String>,
27 pub old_line: Option<usize>,
29 pub new_line: Option<usize>,
31}
32
33impl ChangeSpan {
34 pub fn new(kind: ChangeKind, text: impl Into<String>) -> Self {
35 Self {
36 kind,
37 text: text.into(),
38 new_text: None,
39 old_line: None,
40 new_line: None,
41 }
42 }
43
44 pub fn insert(text: impl Into<String>) -> Self {
45 Self::new(ChangeKind::Insert, text)
46 }
47
48 pub fn delete(text: impl Into<String>) -> Self {
49 Self::new(ChangeKind::Delete, text)
50 }
51
52 pub fn equal(text: impl Into<String>) -> Self {
53 Self::new(ChangeKind::Equal, text)
54 }
55
56 pub fn replace(old: impl Into<String>, new: impl Into<String>) -> Self {
57 Self {
58 kind: ChangeKind::Replace,
59 text: old.into(),
60 new_text: Some(new.into()),
61 old_line: None,
62 new_line: None,
63 }
64 }
65
66 pub fn with_lines(mut self, old_line: Option<usize>, new_line: Option<usize>) -> Self {
67 self.old_line = old_line;
68 self.new_line = new_line;
69 self
70 }
71
72 pub fn is_change(&self) -> bool {
74 self.kind != ChangeKind::Equal
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
80pub struct Change {
81 pub id: usize,
83 pub spans: Vec<ChangeSpan>,
85 pub description: Option<String>,
87}
88
89impl Change {
90 pub fn new(id: usize, spans: Vec<ChangeSpan>) -> Self {
91 Self {
92 id,
93 spans,
94 description: None,
95 }
96 }
97
98 pub fn single(id: usize, span: ChangeSpan) -> Self {
99 Self::new(id, vec![span])
100 }
101
102 pub fn with_description(mut self, desc: impl Into<String>) -> Self {
103 self.description = Some(desc.into());
104 self
105 }
106
107 pub fn changes(&self) -> impl Iterator<Item = &ChangeSpan> {
109 self.spans.iter().filter(|s| s.is_change())
110 }
111
112 pub fn has_changes(&self) -> bool {
114 self.spans.iter().any(|s| s.is_change())
115 }
116}