1use crate::Diff;
5use serde::Deserialize;
6use serde::Serialize;
7use std::fmt::Debug;
8use std::fmt::Formatter;
9
10#[derive(Clone, PartialEq, Serialize, Deserialize)]
12#[serde(transparent)]
13pub struct DiffVec<T: Diff>(pub Vec<InnerVec<T>>);
14
15#[derive(Clone, PartialEq, Serialize, Deserialize)]
17#[serde(untagged)]
18pub enum InnerVec<T: Diff> {
19 Change { index: usize, item: <T as Diff>::Type },
21 Remove { count: usize },
23 Add(<T as Diff>::Type),
25}
26
27impl<T> Diff for Vec<T>
29where
30 T: Clone + Debug + PartialEq + Diff + for<'de> Deserialize<'de> + Serialize,
31{
32 type Type = DiffVec<T>;
34
35 fn diff(&self, other: &Self) -> crate::Result<Self::Type> {
37 let (l_len, r_len) = (self.len(), other.len());
38 let max = usize::max(l_len, r_len);
39 let mut changes: Vec<InnerVec<T>> = vec![];
40
41 for index in 0..max {
42 match (self.get(index), other.get(index)) {
43 (None, None) => panic!("No data to match"),
44 (Some(x), Some(y)) if x == y => {}
45 (Some(x), Some(y)) => changes.push(InnerVec::Change {
46 index,
47 item: x.diff(y)?,
48 }),
49 (None, Some(x)) => changes.push(InnerVec::Add(x.clone().into_diff()?)),
50 (Some(_), None) => match changes.last_mut() {
51 Some(InnerVec::Remove { ref mut count }) => *count += 1,
52 _ => changes.push(InnerVec::Remove { count: 1 }),
53 },
54 }
55 }
56
57 Ok(DiffVec(changes))
58 }
59
60 fn merge(&self, diff: Self::Type) -> crate::Result<Self> {
62 let mut vec: Self = self.clone();
63
64 for change in diff.0.into_iter() {
65 match change {
66 InnerVec::Add(d) => vec.push(<T>::from_diff(d)?),
67 InnerVec::Change { index, item } => vec[index] = self[index].merge(item)?,
68 InnerVec::Remove { count } => {
69 for _ in 0..count {
70 vec
71 .pop()
72 .ok_or_else(|| crate::Error::MergeError("Unable to pop value".into()))?;
73 }
74 }
75 }
76 }
77
78 Ok(vec)
79 }
80
81 fn from_diff(diff: Self::Type) -> crate::Result<Self> {
83 let mut vec: Vec<T> = vec![];
84
85 for (_idx, elm) in diff.0.into_iter().enumerate() {
86 match elm {
87 InnerVec::Add(add) => vec.push(<T>::from_diff(add)?),
88 InnerVec::Change { index: _, item } => {
89 vec.push(<T>::from_diff(item)?);
90 }
91 _ => {}
92 }
93 }
94
95 Ok(vec)
96 }
97
98 fn into_diff(self) -> crate::Result<Self::Type> {
100 let mut changes: Vec<InnerVec<T>> = vec![];
101 for inner in self {
102 changes.push(InnerVec::Add(inner.into_diff()?));
103 }
104 Ok(DiffVec(changes))
105 }
106}
107
108impl<T: Diff> Debug for DiffVec<T> {
110 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
111 write!(f, "DiffVec ")?;
112 f.debug_list().entries(self.0.iter()).finish()
113 }
114}
115
116impl<T: Diff> Debug for InnerVec<T> {
118 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
119 match &self {
120 Self::Change { index, item } => f
121 .debug_struct("Change")
122 .field("index", index)
123 .field("item", item)
124 .finish(),
125 Self::Remove { count } => f.debug_struct("Remove").field("count", count).finish(),
126 Self::Add(diff) => f.debug_tuple("Add").field(diff).finish(),
127 }
128 }
129}
130
131impl<T: Diff> Default for DiffVec<T> {
133 fn default() -> Self {
134 DiffVec(Vec::new())
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_diff_same_val() {
144 let vec_a: Vec<i32> = vec![1, 2, 3];
145 let vec_b: Vec<i32> = vec![1, 2, 3];
146
147 assert_eq!(vec_a, vec_b);
148
149 let diff = vec_a.diff(&vec_b).unwrap();
150
151 assert_eq!(diff, DiffVec(vec![]));
152
153 let vec_c = vec_a.merge(diff).unwrap();
154
155 assert_eq!(vec_b, vec_c);
156
157 let diff = vec_b.diff(&vec_a).unwrap();
158
159 assert_eq!(diff, DiffVec(vec![]));
160
161 let vec_c = vec_b.merge(diff).unwrap();
162
163 assert_eq!(vec_a, vec_c);
164 }
165
166 #[test]
167 fn test_different_vals() {
168 let vec_a = vec![1, 2, 3, 4, 5];
169 let vec_b = vec![4, 2, 3, 4, 6];
170
171 let diff = vec_a.diff(&vec_b).unwrap();
172
173 assert_eq!(
174 diff,
175 DiffVec(vec![
176 InnerVec::Change {
177 index: 0,
178 item: 4i32.into_diff().unwrap(),
179 },
180 InnerVec::Change {
181 index: 4,
182 item: 6i32.into_diff().unwrap(),
183 }
184 ])
185 );
186
187 let vec_c = vec_a.merge(diff).unwrap();
188
189 assert_eq!(vec_b, vec_c);
190
191 let diff = vec_b.diff(&vec_a).unwrap();
192
193 assert_eq!(
194 diff,
195 DiffVec(vec![
196 InnerVec::Change {
197 index: 0,
198 item: 1i32.into_diff().unwrap(),
199 },
200 InnerVec::Change {
201 index: 4,
202 item: 5i32.into_diff().unwrap(),
203 }
204 ])
205 );
206
207 let vec_c = vec_b.merge(diff).unwrap();
208
209 assert_eq!(vec_a, vec_c);
210 }
211
212 #[test]
213 fn test_diff_lengths() {
214 let vec_a = vec![1, 2, 3, 4, 5, 6];
215 let vec_b = vec![1, 2, 3, 4, 6, 7, 8];
216
217 let diff = vec_a.diff(&vec_b).unwrap();
218
219 assert_eq!(
220 diff,
221 DiffVec(vec![
222 InnerVec::Change {
223 index: 4,
224 item: 6i32.into_diff().unwrap(),
225 },
226 InnerVec::Change {
227 index: 5,
228 item: 7i32.into_diff().unwrap(),
229 },
230 InnerVec::Add(8.into_diff().unwrap())
231 ])
232 );
233
234 let vec_c = vec_a.merge(diff).unwrap();
235
236 assert_eq!(vec_b, vec_c);
237
238 let diff = vec_b.diff(&vec_a).unwrap();
239
240 assert_eq!(
241 diff,
242 DiffVec(vec![
243 InnerVec::Change {
244 index: 4,
245 item: 5i32.into_diff().unwrap(),
246 },
247 InnerVec::Change {
248 index: 5,
249 item: 6i32.into_diff().unwrap(),
250 },
251 InnerVec::Remove { count: 1 },
252 ])
253 );
254
255 let vec_c = vec_b.merge(diff).unwrap();
256
257 assert_eq!(vec_a, vec_c);
258 }
259}
260
261#[test]
262fn test_into_from_diff() {
263 let vec_a = vec![1, 2, 3, 4, 5, 6];
264 let vec_b = vec![2, 3, 4, 3, 2, 1, 10, 20];
265
266 let diff = vec_a.diff(&vec_b).unwrap();
267
268 let vec = Vec::from_diff(diff).unwrap();
269
270 assert_eq!(vec, vec_b);
271}