use crate::errors::{CheckError, UniError};
use ahash::AHashSet;
use rkyv::{
Archive, Deserialize, Serialize,
api::high::{to_bytes_in_with_alloc, to_bytes_with_alloc},
de::Pool,
rancor::{Error, Strategy},
ser::{
Serializer,
allocator::{Arena, ArenaHandle},
sharing::Share,
},
util::AlignedVec,
};
use std::future::Future;
use uuid::Uuid;
pub trait Aggregate: Send + Clone + 'static {
fn new(id: Uuid) -> Self;
fn next(&mut self);
fn id(&self) -> Uuid;
fn revision(&self) -> u64;
fn type_name() -> &'static str;
}
pub trait Event:
Archive + for<'m> Serialize<Strategy<Serializer<Vec<u8>, ArenaHandle<'m>, Share>, Error>> + 'static
{
type A: Aggregate;
fn apply(&self, agg: &mut Self::A);
#[inline]
fn process(&self, agg: &mut Self::A) {
self.apply(agg);
agg.next();
}
}
pub trait Command:
Archive
+ Sized
+ Clone
+ for<'m> Serialize<Strategy<Serializer<Vec<u8>, ArenaHandle<'m>, Share>, Error>>
+ 'static
{
type A: Aggregate;
type E: Event<A = Self::A>;
fn check(&self, agg: &Self::A) -> Result<(), CheckError>;
fn apply(self, agg: &Self::A) -> Self::E;
#[inline]
fn process(self, na: &mut Self::A) -> Result<Self::E, UniError> {
self.check(&na)?;
let evt = self.apply(&na);
evt.process(na);
Ok(evt)
}
#[inline(always)]
fn to_bytes_in(&self, arena: &mut Arena) -> Result<Vec<u8>, Error> {
Ok(to_bytes_in_with_alloc(self, Vec::new(), arena.acquire())?)
}
}
pub trait EventEnum:
Send
+ Archive
+ Sized
+ for<'m> Serialize<Strategy<Serializer<AlignedVec, ArenaHandle<'m>, Share>, Error>>
+ 'static
where
<Self as Archive>::Archived: Deserialize<Self, Strategy<Pool, Error>>,
{
type A: Aggregate;
#[inline(always)]
fn to_bytes(&self, arena: &mut Arena) -> Result<AlignedVec, UniError> {
Ok(to_bytes_with_alloc(self, arena.acquire())?)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Result<Self, UniError> {
let required_align = std::mem::align_of::<Self::Archived>();
if bytes.as_ptr().align_offset(required_align) == 0 {
Ok(unsafe { rkyv::from_bytes_unchecked::<Self, Error>(bytes) }?)
} else {
let mut aligned = AlignedVec::<16>::with_capacity(bytes.len());
aligned.extend_from_slice(bytes);
Ok(unsafe { rkyv::from_bytes_unchecked::<Self, Error>(&aligned) }?)
}
}
}
pub trait CommandEnum:
Send
+ Archive
+ Sized
+ Sync
+ Clone
+ for<'m> Serialize<Strategy<Serializer<AlignedVec, ArenaHandle<'m>, Share>, Error>>
+ 'static
where
<Self as Archive>::Archived: Deserialize<Self, Strategy<Pool, Error>>,
<<Self as CommandEnum>::E as Archive>::Archived:
Deserialize<<Self as CommandEnum>::E, Strategy<Pool, Error>>,
{
type A: Aggregate;
type E: EventEnum<A = Self::A>;
fn apply(
self,
topic: &'static str,
agg_id: Uuid,
checkpoint: [u8; 8],
agg: Self::A,
coms: &mut AHashSet<[u8; 16]>,
loader: impl Load<Self::E>,
) -> impl Future<Output = Result<(Self::A, Self::E), UniError>> + Send;
#[inline(always)]
fn to_bytes(&self, arena: &mut Arena) -> Result<AlignedVec, UniError> {
Ok(to_bytes_with_alloc(self, arena.acquire())?)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Result<Self, UniError> {
let required_align = std::mem::align_of::<Self::Archived>();
if bytes.as_ptr().align_offset(required_align) == 0 {
Ok(unsafe { rkyv::from_bytes_unchecked::<Self, Error>(bytes) }?)
} else {
let mut aligned = AlignedVec::<16>::with_capacity(bytes.len());
aligned.extend_from_slice(bytes);
Ok(unsafe { rkyv::from_bytes_unchecked::<Self, Error>(&aligned) }?)
}
}
}
pub trait Load<E>: Send + Copy + 'static
where
E: EventEnum,
<E as Archive>::Archived: Deserialize<E, Strategy<Pool, Error>>,
{
type Fut: Future<Output = Result<Vec<([u8; 16], E)>, UniError>> + Send;
fn load(&self, topic: &'static str, agg_id: Uuid, checkpoint: [u8; 8]) -> Self::Fut;
}
pub trait Config: Sized + 'static {
fn get() -> &'static Self;
fn name() -> &'static str;
}