diff/
impls.rs

1use super::utils::find_match;
2use super::*;
3use serde::{Deserialize, Serialize};
4use std::borrow::Cow;
5use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
6use std::fmt::{Debug, Formatter, Result as FmtResult};
7use std::hash::Hash;
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::path::PathBuf;
11use std::rc::Rc;
12use std::sync::Arc;
13
14impl Diff for bool {
15    type Repr = Option<bool>;
16
17    fn diff(&self, other: &Self) -> Self::Repr {
18        if self != other {
19            Some(*other)
20        } else {
21            None
22        }
23    }
24
25    fn apply(&mut self, diff: &Self::Repr) {
26        if let Some(diff) = diff {
27            *self = *diff;
28        }
29    }
30
31    fn identity() -> Self {
32        false
33    }
34}
35
36impl<T> Diff for Arc<T>
37where
38    T: Diff + Clone,
39{
40    type Repr = T::Repr;
41
42    fn diff(&self, other: &Self) -> Self::Repr {
43        self.deref().diff(other.deref())
44    }
45
46    fn apply(&mut self, diff: &Self::Repr) {
47        match Arc::get_mut(self) {
48            Some(m) => m.apply(diff),
49            None => {
50                let mut x = (**self).clone();
51                x.apply(diff);
52                *self = Arc::new(x);
53            }
54        }
55    }
56
57    fn identity() -> Self {
58        Arc::new(T::identity())
59    }
60}
61
62impl<T> Diff for Box<T>
63where
64    T: Diff,
65{
66    type Repr = Box<T::Repr>;
67
68    fn diff(&self, other: &Self) -> Self::Repr {
69        Box::new(self.deref().diff(other.deref()))
70    }
71
72    fn apply(&mut self, diff: &Self::Repr) {
73       self.as_mut().apply(diff.as_ref())
74    }
75
76    fn identity() -> Self {
77        Box::new(T::identity())
78    }
79}
80
81impl<T> Diff for Rc<T>
82where
83    T: Diff + Clone,
84{
85    type Repr = T::Repr;
86
87    fn diff(&self, other: &Self) -> Self::Repr {
88        self.deref().diff(other.deref())
89    }
90
91    fn apply(&mut self, diff: &Self::Repr) {
92        match Rc::get_mut(self) {
93            Some(m) => m.apply(diff),
94            None => {
95                let mut x = (**self).clone();
96                x.apply(diff);
97                *self = Rc::new(x);
98            }
99        }
100    }
101
102    fn identity() -> Self {
103        Rc::new(T::identity())
104    }
105}
106
107macro_rules! diff_tuple {
108    (($($ty:ident),*), ($($access:tt),*)) => {
109        impl<$($ty),*> Diff for ($($ty),*,)
110            where $($ty: Diff),*
111        {
112            type Repr = ($(<$ty>::Repr),*,);
113
114            fn diff(&self, other: &Self) -> Self::Repr {
115                ($(self.$access.diff(&other.$access)),*,)
116            }
117
118            fn apply(&mut self, diff: &Self::Repr) {
119                $(self.$access.apply(&diff.$access));*;
120            }
121
122            fn identity() -> Self {
123                ($(<$ty>::identity()),*,)
124            }
125        }
126    }
127}
128
129diff_tuple!((A), (0));
130diff_tuple!((A, B), (0, 1));
131diff_tuple!((A, B, C), (0, 1, 2));
132diff_tuple!((A, B, C, D), (0, 1, 2, 3));
133diff_tuple!((A, B, C, D, F), (0, 1, 2, 3, 4));
134diff_tuple!((A, B, C, D, F, G), (0, 1, 2, 3, 4, 5));
135diff_tuple!((A, B, C, D, F, G, H), (0, 1, 2, 3, 4, 5, 6));
136diff_tuple!((A, B, C, D, F, G, H, I), (0, 1, 2, 3, 4, 5, 6, 7));
137diff_tuple!((A, B, C, D, F, G, H, I, J), (0, 1, 2, 3, 4, 5, 6, 7, 8));
138diff_tuple!(
139    (A, B, C, D, F, G, H, I, J, K),
140    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
141);
142diff_tuple!(
143    (A, B, C, D, F, G, H, I, J, K, L),
144    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
145);
146diff_tuple!(
147    (A, B, C, D, F, G, H, I, J, K, L, M),
148    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
149);
150diff_tuple!(
151    (A, B, C, D, F, G, H, I, J, K, L, M, N),
152    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
153);
154diff_tuple!(
155    (A, B, C, D, F, G, H, I, J, K, L, M, N, O),
156    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
157);
158diff_tuple!(
159    (A, B, C, D, F, G, H, I, J, K, L, M, N, O, P),
160    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
161);
162diff_tuple!(
163    (A, B, C, D, F, G, H, I, J, K, L, M, N, O, P, Q),
164    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
165);
166diff_tuple!(
167    (A, B, C, D, F, G, H, I, J, K, L, M, N, O, P, Q, R),
168    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
169);
170diff_tuple!(
171    (A, B, C, D, F, G, H, I, J, K, L, M, N, O, P, Q, R, S),
172    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
173);
174
175macro_rules! diff_int {
176    ($($ty:ty),*) => {
177        $(impl Diff for $ty {
178            type Repr = $ty;
179
180            fn diff(&self, other: &Self) -> Self::Repr {
181                other.wrapping_sub(*self)
182            }
183
184            fn apply(&mut self, diff: &Self::Repr) {
185                *self = self.wrapping_add(*diff);
186            }
187
188            fn identity() -> $ty {
189                0
190            }
191        })*
192    };
193}
194
195macro_rules! diff_float {
196    ($($ty:ty),*) => {
197        $(impl Diff for $ty {
198            type Repr = $ty;
199
200            fn diff(&self, other: &Self) -> Self::Repr {
201                other - self
202            }
203
204            fn apply(&mut self, diff: &Self::Repr){
205                *self += diff;
206            }
207
208            fn identity() -> $ty {
209                0.0
210            }
211        })*
212    };
213}
214
215diff_int!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
216
217macro_rules! diff_non_zero_int {
218    ($($ty:ty, $original:ty),*) => {
219        #[cfg(feature = "impl_num")]
220        $(impl Diff for $ty {
221            type Repr = $original;
222
223            fn diff(&self, other: &Self) -> Self::Repr {
224                other.get().wrapping_sub(self.get())
225            }
226
227            fn apply(&mut self, diff: &Self::Repr) {
228                *self = <$ty>::new(self.get() + *diff).unwrap();
229            }
230
231            fn identity() -> $ty {
232                use num::traits::One;
233                <$ty>::new(<$original>::one()).unwrap()
234            }
235        })*
236    };
237}
238
239#[cfg(feature = "impl_num")]
240use std::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
241
242diff_non_zero_int!(NonZeroU8, u8);
243diff_non_zero_int!(NonZeroU16, u16);
244diff_non_zero_int!(NonZeroU32, u32);
245diff_non_zero_int!(NonZeroU64, u64);
246diff_non_zero_int!(NonZeroU128, u128);
247diff_non_zero_int!(NonZeroUsize, usize);
248
249diff_float!(f32, f64);
250
251impl Diff for char {
252    type Repr = Option<char>;
253
254    fn diff(&self, other: &Self) -> Self::Repr {
255        if self != other {
256            Some(*other)
257        } else {
258            None
259        }
260    }
261
262    fn apply(&mut self, diff: &Self::Repr) {
263        if let Some(diff) = diff {
264            *self = *diff
265        }
266    }
267
268    fn identity() -> Self {
269        '\x00'
270    }
271}
272
273impl Diff for String {
274    type Repr = Option<String>;
275
276    fn diff(&self, other: &Self) -> Self::Repr {
277        if self != other {
278            Some(other.clone())
279        } else {
280            None
281        }
282    }
283
284    fn apply(&mut self, diff: &Self::Repr) {
285        if let Some(diff) = diff {
286            *self = diff.clone()
287        }
288    }
289
290    fn identity() -> Self {
291        String::new()
292    }
293}
294
295impl Diff for PathBuf {
296    type Repr = Option<PathBuf>;
297
298    fn diff(&self, other: &Self) -> Self::Repr {
299        if self != other {
300            Some(other.clone())
301        } else {
302            None
303        }
304    }
305
306    fn apply(&mut self, diff: &Self::Repr) {
307        if let Some(diff) = diff {
308            *self = diff.clone()
309        }
310    }
311
312    fn identity() -> Self {
313        PathBuf::new()
314    }
315}
316
317impl<'a> Diff for &'a str {
318    type Repr = Option<&'a str>;
319
320    fn diff(&self, other: &Self) -> Self::Repr {
321        if self != other {
322            Some(other)
323        } else {
324            None
325        }
326    }
327
328    fn apply(&mut self, diff: &Self::Repr) {
329        if let Some(diff) = diff {
330            *self = diff
331        }
332    }
333
334    fn identity() -> Self {
335        Default::default()
336    }
337}
338
339impl<T> Diff for Cow<'_, T>
340where
341    T: ToOwned + PartialEq + ?Sized,
342    <T as ToOwned>::Owned: Clone + Default,
343{
344    /// Note: This was done to make sure a diff is able to outlive its sources,
345    /// which is the most desirable outcome if the diff is to be moved around
346    /// and consumed much later (or even serialized into foreign programs)
347    type Repr = Option<<T as ToOwned>::Owned>;
348
349    fn diff(&self, other: &Self) -> Self::Repr {
350        if self != other {
351            Some(other.clone().into_owned())
352        } else {
353            None
354        }
355    }
356
357    fn apply(&mut self, diff: &Self::Repr) {
358        if let Some(diff) = diff {
359            *self = Cow::Owned(diff.clone())
360        }
361    }
362
363    fn identity() -> Self {
364        Default::default()
365    }
366}
367
368#[derive(Serialize, Deserialize)]
369pub enum OptionDiff<T: Diff> {
370    Some(T::Repr),
371    None,
372    NoChange,
373}
374
375impl<T: Diff + PartialEq> Diff for Option<T> {
376    type Repr = OptionDiff<T>;
377
378    fn diff(&self, other: &Self) -> Self::Repr {
379        match (self, other) {
380            (Some(value), Some(other_value)) => {
381                if value == other_value {
382                    OptionDiff::NoChange
383                } else {
384                    OptionDiff::Some(value.diff(other_value))
385                }
386            }
387            (Some(_), None) => OptionDiff::None,
388            (None, Some(other_value)) => OptionDiff::Some(T::identity().diff(other_value)),
389            (None, None) => OptionDiff::NoChange,
390        }
391    }
392
393    fn apply(&mut self, diff: &Self::Repr) {
394        match diff {
395            OptionDiff::None => *self = None,
396            OptionDiff::Some(change) => {
397                if let Some(value) = self {
398                    value.apply(change);
399                } else {
400                    *self = Some(T::identity().apply_new(change))
401                }
402            }
403            _ => {}
404        }
405    }
406
407    fn identity() -> Self {
408        None
409    }
410}
411
412impl<T: Diff> Debug for OptionDiff<T>
413where
414    T::Repr: Debug,
415{
416    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
417        match &self {
418            OptionDiff::Some(change) => f.debug_tuple("Some").field(change).finish(),
419            OptionDiff::None => write!(f, "None"),
420            OptionDiff::NoChange => write!(f, "NoChange"),
421        }
422    }
423}
424
425impl<T: Diff> PartialEq for OptionDiff<T>
426where
427    T::Repr: PartialEq,
428{
429    fn eq(&self, other: &Self) -> bool {
430        match (self, other) {
431            (OptionDiff::Some(a), OptionDiff::Some(b)) => a == b,
432            (OptionDiff::None, OptionDiff::None) => true,
433            (OptionDiff::NoChange, OptionDiff::NoChange) => true,
434            _ => false,
435        }
436    }
437}
438
439impl<T: Diff> Clone for OptionDiff<T>
440where
441    T::Repr: Clone,
442{
443    fn clone(&self) -> Self {
444        match self {
445            OptionDiff::Some(a) => OptionDiff::Some(a.clone()),
446            OptionDiff::None => OptionDiff::None,
447            OptionDiff::NoChange => OptionDiff::NoChange,
448        }
449    }
450}
451
452/// The diff struct used to compare two [HashMap]'s
453#[derive(Serialize, Deserialize)]
454#[serde(bound(serialize = "V::Repr: Serialize, K: Serialize"))]
455#[serde(bound(deserialize = "V::Repr: Deserialize<'de>, K: Deserialize<'de>"))]
456pub struct HashMapDiff<K: Hash + Eq, V: Diff> {
457    /// Values that are changed or added
458    pub altered: HashMap<K, <V as Diff>::Repr>,
459    /// Values that are removed
460    pub removed: HashSet<K>,
461}
462
463/// The diff struct used to compare two [BTreeMap]'s
464#[derive(Serialize, Deserialize)]
465#[serde(bound(serialize = "V::Repr: Serialize, K: Serialize"))]
466#[serde(bound(deserialize = "V::Repr: Deserialize<'de>, K: Deserialize<'de>"))]
467pub struct BTreeMapDiff<K: Ord + Eq, V: Diff> {
468    /// Values that are changed or added
469    pub altered: BTreeMap<K, <V as Diff>::Repr>,
470    /// Values that are removed
471    pub removed: BTreeSet<K>,
472}
473
474macro_rules! diff_map {
475    ($ty: ident, $diffty: ident, $diffkey: ident, ($($constraints:tt)*)) => {
476        impl<K: $($constraints)*, V: Diff> Diff for $ty<K, V>
477        where
478            K: Clone,
479            V: PartialEq,
480        {
481            type Repr = $diffty<K, V>;
482
483            fn diff(&self, other: &Self) -> Self::Repr {
484                let mut diff = $diffty {
485                    altered: $ty::new(),
486                    removed: $diffkey::new(),
487                };
488                // can we do better than this?
489                for (key, value) in self {
490                    if let Some(other_value) = other.get(key) {
491                        // don't store values that don't change
492                        if value != other_value {
493                            diff.altered.insert(key.clone(), value.diff(other_value));
494                        }
495                    } else {
496                        diff.removed.insert(key.clone());
497                    }
498                }
499                for (key, value) in other {
500                    if let None = self.get(key) {
501                        diff.altered.insert(key.clone(), V::identity().diff(value));
502                    }
503                }
504                diff
505            }
506
507            // basically inexpensive
508            fn apply(&mut self, diff: &Self::Repr) {
509                diff.removed.iter().for_each(|del| {
510                    self.remove(del);
511                });
512                for (key, change) in &diff.altered {
513                    if let Some(original) = self.get_mut(key) {
514                        original.apply(change);
515                    } else {
516                        self.insert(key.clone(), V::identity().apply_new(change));
517                    }
518                }
519            }
520
521            fn identity() -> Self {
522                $ty::new()
523            }
524        }
525
526        impl<K: $($constraints)*, V: Diff> Debug for $diffty<K, V>
527        where
528            K: Debug,
529            V::Repr: Debug,
530        {
531            fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
532                f.debug_struct(stringify!($diffty))
533                    .field("altered", &self.altered)
534                    .field("removed", &self.removed)
535                    .finish()
536            }
537        }
538
539        impl<K: $($constraints)*, V: Diff> PartialEq for $diffty<K, V>
540        where
541            V::Repr: PartialEq,
542        {
543            fn eq(&self, other: &Self) -> bool {
544                self.altered == other.altered && self.removed == other.removed
545            }
546        }
547
548        impl<K: $($constraints)*, V: Diff> Clone for $diffty<K, V>
549        where
550            K: Clone,
551            V::Repr: Clone,
552        {
553            fn clone(&self) -> Self {
554                $diffty {
555                    altered: self.altered.clone(),
556                    removed: self.removed.clone(),
557                }
558            }
559        }
560    }
561}
562
563diff_map!(HashMap, HashMapDiff, HashSet, (Hash + Eq));
564diff_map!(BTreeMap, BTreeMapDiff, BTreeSet, (Ord));
565
566/// The diff struct used to compare two [HashSet]'s
567#[derive(Serialize, Deserialize)]
568#[serde(bound(serialize = "T: Serialize"))]
569#[serde(bound(deserialize = "T: Deserialize<'de>"))]
570pub struct HashSetDiff<T: Hash + Eq> {
571    /// Values that are added
572    pub added: HashSet<T>,
573    /// Values that are removed
574    pub removed: HashSet<T>,
575}
576
577/// The diff struct used to compare two [BTreeMap]'s
578#[derive(Serialize, Deserialize)]
579#[serde(bound(serialize = "T: Serialize"))]
580#[serde(bound(deserialize = "T: Deserialize<'de>"))]
581pub struct BTreeSetDiff<T: Ord + Eq> {
582    /// Values that are added
583    pub added: BTreeSet<T>,
584    /// Values that are removed
585    pub removed: BTreeSet<T>,
586}
587
588macro_rules! diff_set {
589    ($ty: ident, $diffty: ident, $diffkey: ident, ($($constraints:tt)*)) => {
590        impl<T: $($constraints)*> Diff for $ty<T>
591        where
592            T: Clone,
593        {
594            type Repr = $diffty<T>;
595
596            fn diff(&self, other: &Self) -> Self::Repr {
597                let mut diff = $diffty {
598                    added: $diffkey::new(),
599                    removed: $diffkey::new(),
600                };
601                for value in self {
602                    if !other.contains(value) {
603                        diff.removed.insert(value.clone());
604                    }
605                }
606                for value in other {
607                    if !self.contains(value) {
608                        diff.added.insert(value.clone());
609                    }
610                }
611                diff
612            }
613
614            // basically inexpensive
615            fn apply(&mut self, diff: &Self::Repr) {
616                diff.removed.iter().for_each(|del| {
617                    self.remove(del);
618                });
619                diff.added.iter().for_each(|add| {
620                    self.insert(add.clone());
621                });
622            }
623
624            fn identity() -> Self {
625                $ty::new()
626            }
627        }
628
629        impl<T: $($constraints)*> Debug for $diffty<T>
630        where
631            T: Debug,
632        {
633            fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
634                f.debug_struct(stringify!($diffty))
635                    .field("added", &self.added)
636                    .field("removed", &self.removed)
637                    .finish()
638            }
639        }
640
641        impl<T: $($constraints)*> PartialEq for $diffty<T>
642        where
643            T: PartialEq,
644        {
645            fn eq(&self, other: &Self) -> bool {
646                self.added == other.added && self.removed == other.removed
647            }
648        }
649
650        impl<T: $($constraints)*> Clone for $diffty<T>
651        where
652            T: Clone,
653        {
654            fn clone(&self) -> Self {
655                $diffty {
656                    added: self.added.clone(),
657                    removed: self.removed.clone(),
658                }
659            }
660        }
661    }
662}
663
664diff_set!(HashSet, HashSetDiff, HashSet, (Hash + Eq));
665diff_set!(BTreeSet, BTreeSetDiff, BTreeSet, (Ord));
666
667/// The type of change to make to a vec
668#[derive(Serialize, Deserialize)]
669#[serde(bound(serialize = "T::Repr: Serialize"))]
670#[serde(bound(deserialize = "T::Repr: Deserialize<'de>"))]
671pub enum VecDiffType<T: Diff> {
672    Removed { index: usize, len: usize },
673    Altered { index: usize, changes: Vec<T::Repr> },
674    Inserted { index: usize, changes: Vec<T::Repr> },
675}
676
677/// The collection of difference-vec's
678#[derive(Serialize, Deserialize)]
679#[serde(bound(serialize = "T::Repr: Serialize"))]
680#[serde(bound(deserialize = "T::Repr: Deserialize<'de>"))]
681pub struct VecDiff<T: Diff>(pub Vec<VecDiffType<T>>);
682
683impl<T: Diff + PartialEq> Diff for Vec<T> {
684    type Repr = VecDiff<T>;
685
686    fn diff(&self, other: &Self) -> Self::Repr {
687        let mut changes = Vec::new();
688        let mut pos_x = 0;
689        let mut pos_y = 0;
690        loop {
691            let (is_match, deletions, insertions) = find_match(&self[pos_x..], &other[pos_y..]);
692
693            // TODO: simplify logic here
694            if deletions == 0 || insertions == 0 {
695                if deletions > 0 {
696                    changes.push(VecDiffType::Removed {
697                        index: pos_x,
698                        len: deletions,
699                    });
700                } else if insertions > 0 {
701                    changes.push(VecDiffType::Inserted {
702                        index: pos_x,
703                        changes: other[pos_y..pos_y + insertions]
704                            .iter()
705                            .map(|new| T::identity().diff(new))
706                            .collect(),
707                    });
708                }
709            } else if deletions == insertions {
710                changes.push(VecDiffType::Altered {
711                    index: pos_x,
712                    changes: self[pos_x..pos_x + deletions]
713                        .iter()
714                        .zip(other[pos_y..pos_y + insertions].iter())
715                        .map(|(a, b)| a.diff(b))
716                        .collect(),
717                });
718            } else if deletions > insertions {
719                changes.push(VecDiffType::Altered {
720                    index: pos_x,
721                    changes: self[pos_x..pos_x + insertions]
722                        .iter()
723                        .zip(other[pos_y..pos_y + insertions].iter())
724                        .map(|(a, b)| a.diff(b))
725                        .collect(),
726                });
727                changes.push(VecDiffType::Removed {
728                    index: pos_x + insertions,
729                    len: deletions - insertions,
730                });
731            } else {
732                changes.push(VecDiffType::Altered {
733                    index: pos_x,
734                    changes: self[pos_x..pos_x + deletions]
735                        .iter()
736                        .zip(other[pos_y..pos_y + deletions].iter())
737                        .map(|(a, b)| a.diff(b))
738                        .collect(),
739                });
740                changes.push(VecDiffType::Inserted {
741                    index: pos_x + deletions,
742                    changes: other[pos_y + deletions..pos_y + insertions]
743                        .iter()
744                        .map(|new| T::identity().diff(new))
745                        .collect(),
746                });
747            }
748
749            if is_match {
750                pos_x += deletions + 1;
751                pos_y += insertions + 1;
752            } else {
753                break;
754            }
755        }
756        VecDiff(changes)
757    }
758
759    fn apply(&mut self, diff: &Self::Repr) {
760        let mut relative_index = 0_isize;
761        for change in &diff.0 {
762            match change {
763                VecDiffType::Removed { index, len } => {
764                    let index = (*index as isize + relative_index) as usize;
765                    self.drain(index..index + len);
766                    relative_index -= *len as isize;
767                }
768                VecDiffType::Inserted { index, changes } => {
769                    let index = (*index as isize + relative_index) as usize;
770                    self.splice(
771                        index..index,
772                        changes.iter().map(|d| T::identity().apply_new(d)),
773                    );
774                    relative_index += changes.len() as isize;
775                }
776                VecDiffType::Altered { index, changes } => {
777                    let index = (*index as isize + relative_index) as usize;
778                    let range = index..index + changes.len();
779                    for (value, diff) in self[range].iter_mut().zip(changes.iter()) {
780                        value.apply(diff);
781                    }
782                }
783            }
784        }
785    }
786
787    fn identity() -> Self {
788        Vec::new()
789    }
790}
791
792impl<T: Diff> Debug for VecDiffType<T>
793where
794    T::Repr: Debug,
795{
796    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
797        match self {
798            VecDiffType::Removed { index, len } => f
799                .debug_struct("Removed")
800                .field("index", index)
801                .field("len", len)
802                .finish(),
803            VecDiffType::Altered { index, changes } => f
804                .debug_struct("Altered")
805                .field("index", index)
806                .field("changes", changes)
807                .finish(),
808            VecDiffType::Inserted { index, changes } => f
809                .debug_struct("Inserted")
810                .field("index", index)
811                .field("changes", changes)
812                .finish(),
813        }
814    }
815}
816
817impl<T: Diff> PartialEq for VecDiffType<T>
818where
819    T::Repr: PartialEq,
820{
821    fn eq(&self, other: &Self) -> bool {
822        match (self, other) {
823            (
824                VecDiffType::Removed { index, len },
825                VecDiffType::Removed {
826                    index: ref index_,
827                    len: ref len_,
828                },
829            ) => index == index_ && len == len_,
830            (
831                VecDiffType::Altered { index, changes },
832                VecDiffType::Altered {
833                    index: ref index_,
834                    changes: ref changes_,
835                },
836            ) => index == index_ && changes == changes_,
837            (
838                VecDiffType::Inserted { index, changes },
839                VecDiffType::Inserted {
840                    index: ref index_,
841                    changes: ref changes_,
842                },
843            ) => index == index_ && changes == changes_,
844            _ => false,
845        }
846    }
847}
848
849impl<T: Diff> Clone for VecDiffType<T>
850where
851    T::Repr: Clone,
852{
853    fn clone(&self) -> Self {
854        match self {
855            VecDiffType::Removed { index, len } => VecDiffType::Removed {
856                index: *index,
857                len: *len,
858            },
859            VecDiffType::Altered { index, changes } => VecDiffType::Altered {
860                index: *index,
861                changes: changes.clone(),
862            },
863            VecDiffType::Inserted { index, changes } => VecDiffType::Inserted {
864                index: *index,
865                changes: changes.clone(),
866            },
867        }
868    }
869}
870
871impl<T: Diff> Debug for VecDiff<T>
872where
873    T::Repr: Debug,
874{
875    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
876        f.debug_list().entries(self.0.iter()).finish()
877    }
878}
879
880impl<T: Diff> PartialEq for VecDiff<T>
881where
882    T::Repr: PartialEq,
883{
884    fn eq(&self, other: &Self) -> bool {
885        self.0 == other.0
886    }
887}
888
889impl<T: Diff> Clone for VecDiff<T>
890where
891    T::Repr: Clone,
892{
893    fn clone(&self) -> Self {
894        Self(self.0.clone())
895    }
896}
897
898/// The type of change to make to an array
899#[derive(Serialize, Deserialize)]
900#[serde(bound(serialize = "T::Repr: Serialize"))]
901#[serde(bound(deserialize = "T::Repr: Deserialize<'de>"))]
902pub struct ArrayDiffType<T: Diff> {
903    pub index: usize,
904    pub change: T::Repr,
905}
906
907/// The collection of difference-vec's
908#[derive(Serialize, Deserialize)]
909#[serde(bound(serialize = "T::Repr: Serialize"))]
910#[serde(bound(deserialize = "T::Repr: Deserialize<'de>"))]
911pub struct ArrayDiff<T: Diff>(pub Vec<ArrayDiffType<T>>);
912
913impl<T: Diff + PartialEq, const N: usize> Diff for [T; N] {
914    type Repr = ArrayDiff<T>;
915
916    fn diff(&self, other: &Self) -> Self::Repr {
917        ArrayDiff(
918            self.iter()
919                .zip(other.iter())
920                .enumerate()
921                .filter_map(|(index, (self_el, other_el))| {
922                    self_el.ne(other_el).then(|| ArrayDiffType {
923                        index,
924                        change: self_el.diff(other_el),
925                    })
926                })
927                .collect(),
928        )
929    }
930
931    fn apply(&mut self, diff: &Self::Repr) {
932        for ArrayDiffType { index, change } in &diff.0 {
933            self[*index].apply(change);
934        }
935    }
936
937    fn identity() -> Self {
938        std::array::from_fn(|_| T::identity())
939    }
940}
941
942impl<T: Diff> Debug for ArrayDiffType<T>
943where
944    T::Repr: Debug,
945{
946    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
947        f.debug_struct("ArrayDiffType")
948            .field("index", &self.index)
949            .field("change", &self.change)
950            .finish()
951    }
952}
953
954impl<T: Diff> PartialEq for ArrayDiffType<T>
955where
956    T::Repr: PartialEq,
957{
958    fn eq(&self, other: &Self) -> bool {
959        self.index == other.index && self.change == other.change
960    }
961}
962
963impl<T: Diff> Clone for ArrayDiffType<T>
964where
965    T::Repr: Clone,
966{
967    fn clone(&self) -> Self {
968        Self {
969            index: self.index,
970            change: self.change.clone(),
971        }
972    }
973}
974
975impl<T: Diff> Debug for ArrayDiff<T>
976where
977    T::Repr: Debug,
978{
979    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
980        f.debug_list().entries(self.0.iter()).finish()
981    }
982}
983
984impl<T: Diff> PartialEq for ArrayDiff<T>
985where
986    T::Repr: PartialEq,
987{
988    fn eq(&self, other: &Self) -> bool {
989        self.0 == other.0
990    }
991}
992
993impl<T: Diff> Clone for ArrayDiff<T>
994where
995    T::Repr: Clone,
996{
997    fn clone(&self) -> Self {
998        Self(self.0.clone())
999    }
1000}
1001
1002impl<T> Diff for PhantomData<T> {
1003    type Repr = PhantomData<T>;
1004
1005    fn diff(&self, _other: &Self) -> Self::Repr {
1006        PhantomData::default()
1007    }
1008
1009    fn apply(&mut self, _diff: &Self::Repr) {}
1010
1011    fn identity() -> Self {
1012        PhantomData::default()
1013    }
1014}