diffus/diffable_impls/
borrow.rs1use 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}