use crate::error::DeltaResult;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
pub trait Core {
type Delta: Sized + Clone + Debug + PartialEq
+ for<'de> Deserialize<'de>
+ Serialize;
}
pub trait Apply: Core + Clone + Debug + PartialEq {
fn apply(&self, delta: Self::Delta) -> DeltaResult<Self>;
}
pub trait Delta: Core + Clone + Debug + PartialEq {
fn delta(&self, other: &Self) -> DeltaResult<Self::Delta>;
}
pub trait FromDelta: Core + Sized {
fn from_delta(delta: Self::Delta) -> DeltaResult<Self>;
}
pub trait IntoDelta: Core {
fn into_delta(self) -> DeltaResult<Self::Delta>;
}
macro_rules! impl_delta_trait_for_primitive_types {
( $($type:ty => $delta:ident $(: $($traits:ident),+)?);* $(;)? ) => {
$(
$( #[derive( $($traits),+ )] )?
#[derive(serde_derive::Deserialize, serde_derive::Serialize)]
pub struct $delta(#[doc(hidden)] pub Option<$type>);
impl Core for $type {
type Delta = $delta;
}
impl Apply for $type {
#[inline(always)]
fn apply(&self, delta: Self::Delta) -> DeltaResult<Self> {
Self::from_delta(delta)
}
}
impl Delta for $type {
#[inline(always)]
fn delta(&self, rhs: &Self) -> DeltaResult<Self::Delta> {
rhs.clone().into_delta()
}
}
impl FromDelta for $type {
#[inline(always)]
fn from_delta(delta: Self::Delta) -> DeltaResult<Self> {
delta.0.ok_or_else(|| ExpectedValue!(stringify!($delta)))
}
}
impl IntoDelta for $type {
#[inline(always)]
fn into_delta(self) -> DeltaResult<Self::Delta> {
Ok($delta(Some(self)))
}
}
impl std::fmt::Debug for $delta {
fn fmt(&self, f: &mut std::fmt::Formatter)
-> Result<(), std::fmt::Error>
{
match self.0 {
None =>
write!(f, "{}(None)", stringify!($delta)),
Some(prim) =>
write!(f, "{}({:#?})", stringify!($delta), prim),
}
}
}
)*
};
}
impl_delta_trait_for_primitive_types! {
i8 => I8Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
i16 => I16Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
i32 => I32Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
i64 => I64Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
i128 => I128Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
isize => IsizeDelta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
u8 => U8Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
u16 => U16Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
u32 => U32Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
u64 => U64Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
u128 => U128Delta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
usize => UsizeDelta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
f32 => F32Delta: Clone, Copy, PartialEq, PartialOrd ;
f64 => F64Delta: Clone, Copy, PartialEq, PartialOrd ;
bool => BoolDelta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
char => CharDelta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
() => UnitDelta: Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash;
}