use serde_json::Value;
use crate::{Event, Result};
#[derive(Debug)]
pub struct RawStoredEvent {
pub aggregate_id: String,
pub version: i64,
pub event_version: u16,
pub event_type: String,
pub payload: Value,
}
pub trait Upcaster<E: Event>: Send + Sync {
fn event_type(&self) -> &'static str;
fn source_version(&self) -> u16;
fn target_version(&self) -> u16 {
self.source_version() + 1
}
fn upcast(&self, payload: Value) -> Result<Value>;
}
pub struct UpcasterChain<E: Event> {
upcasters: Vec<Box<dyn Upcaster<E>>>,
}
impl<E: Event> Default for UpcasterChain<E> {
fn default() -> Self {
Self {
upcasters: Vec::new(),
}
}
}
impl<E: Event> UpcasterChain<E> {
pub fn new() -> Self {
Self::default()
}
pub fn with<U: Upcaster<E> + 'static>(mut self, upcaster: U) -> Self {
self.upcasters.push(Box::new(upcaster));
self
}
pub(crate) fn upcast(&self, event: RawStoredEvent) -> Result<RawStoredEvent> {
let mut current_version = event.event_version;
let mut payload = event.payload;
let event_type = event.event_type.clone();
while let Some(upcaster) = self
.upcasters
.iter()
.find(|u| u.event_type() == event_type && u.source_version() == current_version)
{
payload = upcaster.upcast(payload)?;
current_version = upcaster.target_version();
}
Ok(RawStoredEvent {
aggregate_id: event.aggregate_id,
version: event.version,
event_version: current_version,
event_type,
payload,
})
}
}