diffus/diffable_impls/
borrow.rsuse crate::{edit, Diffable};
use std::borrow::Borrow;
fn diff_borrowable<'a, T, C, D>(left: &'a C, right: &'a C) -> edit::Edit<'a, C>
where
T: Diffable<'a> + ?Sized + 'a,
C: Borrow<T> + Diffable<'a, Diff = D> + ?Sized,
D: From<T::Diff>,
{
match left.borrow().diff(right.borrow()) {
edit::Edit::Copy(_) => edit::Edit::Copy(left),
edit::Edit::Change(diff) => edit::Edit::Change(diff.into()),
}
}
macro_rules! borrow_impl {
($($typ:ident),*) => {
$(
impl<'a, T: Diffable<'a> + ?Sized + 'a> Diffable<'a> for $typ<T> {
type Diff = $typ<T::Diff>;
fn diff(&'a self, other: &'a Self) -> edit::Edit<'a, Self> {
diff_borrowable::<T, _, _>(self, other)
}
}
)*
}
}
use std::{rc::Rc, sync::Arc};
borrow_impl! {
Box, Rc, Arc
}
impl<'a, T: Diffable<'a> + ?Sized + 'a> Diffable<'a> for &'a T {
type Diff = T::Diff;
fn diff(&'a self, other: &'a Self) -> edit::Edit<'a, Self> {
diff_borrowable::<T, _, _>(self, other)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn box_example() {
let left = 13;
let right = 37;
if let edit::Edit::Change(diff) = Box::new(left).diff(&Box::new(right)) {
assert_eq!(*diff, (&13, &37));
}
}
#[test]
fn rc_example() {
let left = 13;
let right = 37;
if let edit::Edit::Change(diff) = Rc::new(left).diff(&Rc::new(right)) {
assert_eq!(*diff, (&13, &37));
}
}
#[test]
fn arc_example() {
let left = 13;
let right = 37;
if let edit::Edit::Change(diff) = Arc::new(left).diff(&Arc::new(right)) {
assert_eq!(*diff, (&13, &37));
}
}
#[test]
fn reference_example() {
let left = 13;
let right = 37;
if let edit::Edit::Change(diff) = (&left).diff(&(&right)) {
assert_eq!(diff, (&13, &37));
}
}
}