mutable 0.2.8

Mutable is a crate to keep track of changes in structures
Documentation
//! See [MutableHolder]

use core::clone::Clone;
use std::ops::{Deref, DerefMut};
use crate::Mutable;

/// Store a mutable element and keeps track of its modifications
/// ```
/// # use mutable::holder::MutableHolder;
/// # use mutable_derive::Mutable;
/// 
/// #[derive(Mutable, Clone)]
/// struct Foo{
///     int: i32,
/// }
/// 
/// #[derive(Mutable, Clone)]
/// struct Bar{
///     foo: Foo,
///     int: i32,
/// }
///
/// let mut mh = MutableHolder::new(Bar{ foo: Foo { int: 2 }, int: 3 });
/// 
/// mh.get_mut().int = 4;
/// assert_eq!(mh.get().int, 4);
/// assert_eq!(mh.mutations(), vec![BarMutation::Int((3, 4))]);
/// ```

pub struct MutableHolder<M: Mutable + Clone> {
    old: M,
    current: M,

    mutations: Vec<M::Mutation>,
}

impl<M: Mutable + Clone> MutableHolder<M> {
    pub fn new(value: M) -> MutableHolder<M> {
        MutableHolder{
            old: value.clone(),
            current: value,
            mutations: vec![]
        }
    }

    /// Immutable reference to the stored element
    pub fn get(&self) -> &M { &self.current }

    /// Returns a mutable reference to the stored element, allowing direct modifications
    /// The modifications will be computed when the returned reference is dropped
    pub fn get_mut(&mut self) -> MHRefMut<M> { MHRefMut(self) }

    pub(crate) fn collect_mutations(&mut self) {
        self.mutations.append(&mut self.old.update(self.current.clone()))
    }

    /// Returns the vector of the modifications, and clears the inner mutation buffer
    pub fn mutations(&mut self) -> Vec<M::Mutation> {
        let mutations = self.mutations.clone();
        self.mutations.clear();
        mutations
    }
}

pub struct MHRefMut<'r, M: Mutable + Clone>(&'r mut MutableHolder<M>);

impl<'r, M: Mutable + Clone> Deref for MHRefMut<'r, M> {
    type Target = M;

    fn deref(&self) -> &Self::Target {
        &self.0.current
    }
}

impl<'r, M: Mutable + Clone> DerefMut for MHRefMut<'r, M> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0.current
    }
}

impl<'r, M: Mutable + Clone> Drop for MHRefMut<'r, M> {
    fn drop(&mut self) {
        self.0.collect_mutations();
    }
}