deltastruct 0.1.8

Allows defining deltas for tagged structs for later application.
Documentation
use crate::DeltaStruct;
use paste::paste;
use std::{
  collections::{HashMap, HashSet},
  hash::Hash,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

// Numbers
macro_rules! impl_num {
  ($($tname:ty),*) => {
    $(paste! {
      #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
      #[allow(non_camel_case_types)]
      #[derive(Clone)]
      pub enum [<$tname Delta>] {
        Set($tname),
        Add($tname),
        Sub($tname),
        Mult($tname),
        Div($tname),
        Mod($tname),
      }

      impl DeltaStruct<[<$tname Delta>]> for $tname {
        fn apply(&mut self, delta : &[<$tname Delta>]) {
          match delta {
            [<$tname Delta>]::Set(x) => { *self = *x }
            [<$tname Delta>]::Add(x) => { *self += *x }
            [<$tname Delta>]::Sub(x) => { *self -= *x }
            [<$tname Delta>]::Mult(x) => { *self *= *x }
            [<$tname Delta>]::Div(x) => { *self /= *x }
            [<$tname Delta>]::Mod(x) => { *self %= *x }
          }
        }
      }
    })*
  }
}

impl_num!(i8, i16, i32, i64, u8, u16, u32, u64, usize, isize, f32, f64);

// bool
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[allow(non_camel_case_types)]
#[derive(Clone)]
pub enum boolDelta {
  Set(bool),
  Toggle,
}

impl DeltaStruct<boolDelta> for bool {
  fn apply(&mut self, delta: &boolDelta) {
    match delta {
      boolDelta::Set(x) => *self = *x,
      boolDelta::Toggle => *self = !*self,
    }
  }
}

// char
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[allow(non_camel_case_types)]
#[derive(Clone)]
pub enum charDelta {
  Set(char),
}

impl DeltaStruct<charDelta> for char {
  fn apply(&mut self, delta: &charDelta) {
    match delta {
      charDelta::Set(x) => *self = *x,
    }
  }
}

// String
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
pub enum StringDelta {
  Set(String),
  Append(String),
}

impl DeltaStruct<StringDelta> for String {
  fn apply(&mut self, delta: &StringDelta) {
    match delta {
      StringDelta::Set(x) => *self = x.clone(),
      StringDelta::Append(x) => *self += x,
    }
  }
}

// Vecs
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
pub enum VecDelta<T>
where
  T: Clone,
{
  Set(Vec<T>),
  Push(T),
  Pop(),
}

impl<T> DeltaStruct<VecDelta<T>> for Vec<T>
where
  T: Clone,
{
  fn apply(&mut self, delta: &VecDelta<T>) {
    match delta {
      VecDelta::Set(x) => *self = x.clone(),
      VecDelta::Push(x) => self.push(x.clone()),
      VecDelta::Pop() => {
        self.pop();
      }
    }
  }
}

// Option
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
pub enum OptionDelta<T>
where
  T: Clone,
{
  Set(T),
  Clear,
}

impl<T> DeltaStruct<OptionDelta<T>> for Option<T>
where
  T: Clone,
{
  fn apply(&mut self, delta: &OptionDelta<T>) {
    match delta {
      OptionDelta::Set(x) => *self = Some(x.clone()),
      OptionDelta::Clear => *self = None,
    }
  }
}

// HashSet
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
pub enum HashSetDelta<T>
where
  T: Clone + Eq + Hash,
{
  Set(HashSet<T>),
  Insert(T),
  Remove(T),
}

impl<T> DeltaStruct<HashSetDelta<T>> for HashSet<T>
where
  T: Clone + Eq + Hash,
{
  fn apply(&mut self, delta: &HashSetDelta<T>) {
    match delta {
      HashSetDelta::Set(x) => *self = x.clone(),
      HashSetDelta::Insert(x) => {
        self.insert(x.clone());
      }
      HashSetDelta::Remove(x) => {
        self.remove(x);
      }
    }
  }
}

// HashMap
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
pub enum HashMapDelta<T, U>
where
  T: Clone + Eq + Hash,
  U: Clone,
{
  Set(HashMap<T, U>),
  Insert(T, U),
  Remove(T),
}

impl<T, U> DeltaStruct<HashMapDelta<T, U>> for HashMap<T, U>
where
  T: Clone + Eq + Hash,
  U: Clone,
{
  fn apply(&mut self, delta: &HashMapDelta<T, U>) {
    match delta {
      HashMapDelta::Set(x) => *self = x.clone(),
      HashMapDelta::Insert(k, v) => {
        self.insert(k.clone(), v.clone());
      }
      HashMapDelta::Remove(k) => {
        self.remove(k);
      }
    }
  }
}