mutable 0.2.8

Mutable is a crate to keep track of changes in structures
Documentation
//! Default implementation for native types

#[cfg(feature = "uuid")]
use uuid::Uuid;

use crate::cmp::SoftEq;
use crate::Mutable;

fn simple_cmp<T: PartialEq + Clone>(old: &T, new: &T) -> Vec<(T, T)> {
    if old != new {
        vec![(old.clone(), new.clone())]
    } else {
        vec![]
    }
}

impl Mutable for i8 {
    type Mutation = (i8, i8);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for i16 {
    type Mutation = (i16, i16);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for i32 {
    type Mutation = (i32, i32);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for i64 {
    type Mutation = (i64, i64);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for i128 {
    type Mutation = (i128, i128);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for isize {
    type Mutation = (isize, isize);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for u8 {
    type Mutation = (u8, u8);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for u16 {
    type Mutation = (u16, u16);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for u32 {
    type Mutation = (u32, u32);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for u64 {
    type Mutation = (u64, u64);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for u128 {
    type Mutation = (u128, u128);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for usize {
    type Mutation = (usize, usize);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for bool {
    type Mutation = (bool, bool);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for () {
    type Mutation = ();

    fn cmp(&self, _: &Self) -> Vec<Self::Mutation> {
        vec![]
    }
}

impl Mutable for String {
    type Mutation = (String, String);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        simple_cmp(self, new)
    }
}

impl Mutable for f32 {
    type Mutation = (f32, f32);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        option_env!("f32_eps").map(|eps|
            if (self - new).abs() > eps.parse::<f32>().expect("Could not parse f32_eps") {
                vec![(*self, *new)]
            } else {
                vec![]
            }
        ).unwrap_or_else(|| simple_cmp(self, new))
    }
}

impl Mutable for f64 {
    type Mutation = (f64, f64);

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        option_env!("f64_eps").map(|eps|
            if (self - new).abs() > eps.parse::<f64>().expect("Could not parse f64_eps") {
                vec![(*self, *new)]
            } else {
                vec![]
            }
        ).unwrap_or_else(|| simple_cmp(self, new))
    }
}

#[cfg(feature = "uuid")]
impl Mutable for Uuid{
    type Mutation = (Uuid, Uuid);

    fn cmp(&self, other: &Self) -> Vec<Self::Mutation> {
        (self.eq(other)).then_some((*self, *other)).into_iter().collect()
    }
}

/// Mutations of a Vec<T>
#[derive(PartialEq, Debug, Clone)]
pub enum VecMutation<T: Mutable + SoftEq> {
    Insertion(T::Uid),
    Deletion(T::Uid),
    Update(T::Uid, T::Mutation),
}

impl<T: Mutable + Clone + SoftEq> Mutable for Vec<T> {
    type Mutation = VecMutation<T>;

    fn cmp(&self, new: &Self) -> Vec<Self::Mutation> {
        let mut updates = Vec::new();

        for new_item in new.iter() {
            let curr = self.iter().find(|a| a.se(new_item));

            if let Some(curr) = curr {
                updates.append(&mut curr.cmp(new_item).into_iter().map(|m| VecMutation::Update(curr.uid(), m)).collect::<Vec<VecMutation<T>>>())
            } else {
                updates.push(VecMutation::Insertion(new_item.uid()));
            }
        }

        for old_item in self.iter() {
            if !new.iter().any(|n| old_item.se(n)) {
                updates.push(VecMutation::Deletion(old_item.uid()));
            }
        }

        updates
    }
}

#[derive(PartialEq, Debug, Clone)]
pub enum OptionMutation<T: Mutable>{
    SomeToSome(T::Mutation),
    SomeToNone(T),
    NoneToSome(T),
}

impl<T: Mutable + Clone> Mutable for Option<T>{
    type Mutation = OptionMutation<T>;

    fn cmp(&self, other: &Self) -> Vec<Self::Mutation> {
        match (self, other) {
            (Some(t1), Some(t2)) => t1.cmp(t2).into_iter().map(|m| OptionMutation::SomeToSome(m)).collect(),
            (Some(t), None) =>  vec![OptionMutation::SomeToNone(t.clone())],
            (None, Some(t)) =>  vec![OptionMutation::SomeToNone(t.clone())],
            _ => vec![]
        }
    }
}