diffus/diffable_impls/
borrow.rs

1use crate::{edit, Diffable};
2use std::borrow::Borrow;
3
4fn diff_borrowable<'a, T, C, D>(left: &'a C, right: &'a C) -> edit::Edit<'a, C>
5where
6    T: Diffable<'a> + ?Sized + 'a,
7    C: Borrow<T> + Diffable<'a, Diff = D> + ?Sized,
8    D: From<T::Diff>,
9{
10    match left.borrow().diff(right.borrow()) {
11        edit::Edit::Copy(_) => edit::Edit::Copy(left),
12        edit::Edit::Change(diff) => edit::Edit::Change(diff.into()),
13    }
14}
15
16macro_rules! borrow_impl {
17    ($($typ:ident),*) => {
18        $(
19            impl<'a, T: Diffable<'a> + ?Sized + 'a> Diffable<'a> for $typ<T> {
20                type Diff = $typ<T::Diff>;
21
22                fn diff(&'a self, other: &'a Self) -> edit::Edit<'a, Self> {
23                    diff_borrowable::<T, _, _>(self, other)
24                }
25            }
26        )*
27    }
28}
29
30use std::{rc::Rc, sync::Arc};
31borrow_impl! {
32    Box, Rc, Arc
33}
34
35impl<'a, T: Diffable<'a> + ?Sized + 'a> Diffable<'a> for &'a T {
36    type Diff = T::Diff;
37
38    fn diff(&'a self, other: &'a Self) -> edit::Edit<'a, Self> {
39        diff_borrowable::<T, _, _>(self, other)
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn box_example() {
49        let left = 13;
50        let right = 37;
51
52        if let edit::Edit::Change(diff) = Box::new(left).diff(&Box::new(right)) {
53            assert_eq!(*diff, (&13, &37));
54        }
55    }
56
57    #[test]
58    fn rc_example() {
59        let left = 13;
60        let right = 37;
61
62        if let edit::Edit::Change(diff) = Rc::new(left).diff(&Rc::new(right)) {
63            assert_eq!(*diff, (&13, &37));
64        }
65    }
66
67    #[test]
68    fn arc_example() {
69        let left = 13;
70        let right = 37;
71
72        if let edit::Edit::Change(diff) = Arc::new(left).diff(&Arc::new(right)) {
73            assert_eq!(*diff, (&13, &37));
74        }
75    }
76
77    #[test]
78    fn reference_example() {
79        let left = 13;
80        let right = 37;
81
82        if let edit::Edit::Change(diff) = (&left).diff(&(&right)) {
83            assert_eq!(diff, (&13, &37));
84        }
85    }
86}