java_diff_utils_rs/patch/
change_delta.rs1use std::fmt;
2
3use super::chunk::Chunk;
4use super::delta::Delta;
5use super::delta_type::DeltaType;
6use super::error::PatchError;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct ChangeDelta<T> {
11 inner: Delta<T>,
12}
13
14impl<T> ChangeDelta<T> {
15 pub fn new(source: Chunk<T>, target: Chunk<T>) -> Self {
17 Self {
18 inner: Delta::new(DeltaType::Change, source, target),
19 }
20 }
21
22 #[inline]
24 pub fn delta(&self) -> &Delta<T> {
25 &self.inner
26 }
27
28 #[inline]
30 pub fn into_delta(self) -> Delta<T> {
31 self.inner
32 }
33
34 #[inline]
36 pub fn source(&self) -> &Chunk<T> {
37 self.inner.source()
38 }
39
40 #[inline]
42 pub fn target(&self) -> &Chunk<T> {
43 self.inner.target()
44 }
45
46 pub fn apply_to(&self, target: &mut Vec<T>) -> Result<(), PatchError>
50 where
51 T: Clone + PartialEq,
52 {
53 let position = self.source().position();
54 let source_size = self.source().len();
55
56 if position > target.len() || position + source_size > target.len() {
57 return Err(PatchError::PatchFailed(format!(
58 "ChangeDelta position {} (size {}) out of bounds for target length {}",
59 position,
60 source_size,
61 target.len()
62 )));
63 }
64
65 target.splice(
67 position..position + source_size,
68 self.target().lines().iter().cloned(),
69 );
70
71 Ok(())
72 }
73
74 pub fn restore(&self, target: &mut Vec<T>) -> Result<(), PatchError>
78 where
79 T: Clone + PartialEq,
80 {
81 let position = self.target().position();
82 let target_size = self.target().len();
83
84 if position > target.len() || position + target_size > target.len() {
85 return Err(PatchError::PatchFailed(format!(
86 "ChangeDelta restore position {} (size {}) out of bounds for target length {}",
87 position,
88 target_size,
89 target.len()
90 )));
91 }
92
93 target.splice(
94 position..position + target_size,
95 self.source().lines().iter().cloned(),
96 );
97
98 Ok(())
99 }
100
101 pub fn apply_fuzzy_to_at(
103 &self,
104 target: &mut Vec<T>,
105 _fuzz: usize,
106 position: usize,
107 ) -> Result<(), PatchError>
108 where
109 T: Clone + PartialEq,
110 {
111 if position > target.len() {
112 return Err(PatchError::PatchFailed(format!(
113 "Fuzzy patch position {} out of bounds for target length {}",
114 position,
115 target.len()
116 )));
117 }
118
119 let end = (position + self.source().len()).min(target.len());
120
121 target.splice(position..end, self.target().lines().iter().cloned());
122
123 Ok(())
124 }
125
126 #[must_use]
128 pub fn with_chunks(&self, original: Chunk<T>, revised: Chunk<T>) -> Self {
129 Self::new(original, revised)
130 }
131}
132
133impl<T: fmt::Debug> fmt::Display for ChangeDelta<T> {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(
136 f,
137 "[ChangeDelta, position: {}, lines: {:?} to {:?}]",
138 self.source().position(),
139 self.source().lines(),
140 self.target().lines()
141 )
142 }
143}
144
145impl<T> From<ChangeDelta<T>> for Delta<T> {
146 fn from(change: ChangeDelta<T>) -> Self {
147 change.inner
148 }
149}