use crate::Timestamp;
use chrono::Utc;
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, cmp::Ordering, ops::Deref};
#[derive(Clone, PartialEq, Serialize, Debug, Deserialize)]
pub enum Event<'a, T>
where
T: Clone + PartialEq,
{
Create(EventContent<'a, T>),
Update(EventContent<'a, T>),
Delete(EventContent<'a, T>),
}
#[derive(Clone, PartialEq, Serialize, Debug, Deserialize)]
pub struct EventContent<'a, T>
where
T: Clone + PartialEq,
{
timestamp: Timestamp,
data: Cow<'a, T>,
}
impl<'a, T> Event<'a, T>
where
T: Clone + PartialEq,
{
pub fn create(data: Cow<'a, T>) -> Self {
Self::Create(EventContent {
timestamp: Utc::now(),
data,
})
}
pub fn update(data: Cow<'a, T>) -> Self {
Self::Update(EventContent {
timestamp: Utc::now(),
data,
})
}
pub fn delete(data: Cow<'a, T>) -> Self {
Self::Delete(EventContent {
timestamp: Utc::now(),
data,
})
}
fn borrow_inner(&self) -> &T {
&match self {
Self::Create(ref data) | Self::Update(ref data) | Self::Delete(ref data) => data,
}
.data
}
pub fn get_time(&self) -> &Timestamp {
&match self {
Self::Create(ref data) | Self::Update(ref data) | Self::Delete(ref data) => data,
}
.timestamp
}
fn compare_timestamps(&self, other: &Self) -> Ordering {
let (t1, t2) = (self.get_time(), other.get_time());
if t1 < t2 {
Ordering::Less
} else if t1 > t2 {
Ordering::Greater
} else {
Ordering::Equal
}
}
pub fn take(self) -> Cow<'a, T> {
match self {
Self::Create(data) | Self::Update(data) | Self::Delete(data) => data,
}
.data
}
}
impl<'a, T> Deref for Event<'a, T>
where
T: Clone + PartialEq,
{
type Target = T;
fn deref(&self) -> &Self::Target {
self.borrow_inner()
}
}
impl<'a, T> PartialOrd for Event<'a, T>
where
T: Clone + PartialEq,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.compare_timestamps(other))
}
}