use serde_json::Value;
use crate::core::StoreError;
pub trait Upcaster: Send + Sync + std::fmt::Debug {
fn current_version(&self, kind: &str) -> u16;
fn upcast(&self, kind: &str, version: u16, payload: Value) -> Result<Value, StoreError>;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Identity;
impl Upcaster for Identity {
fn current_version(&self, _kind: &str) -> u16 {
1
}
fn upcast(&self, kind: &str, version: u16, payload: Value) -> Result<Value, StoreError> {
if version == 1 {
Ok(payload)
} else {
Err(StoreError::Corrupt {
seq: 0,
detail: format!(
"record {kind} v{version} is newer than this build understands (v1) — \
readers must be deployed before writers"
),
})
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn future_versions_are_refused_not_guessed() {
let err = Identity.upcast("EffectDone", 7, json!({})).unwrap_err();
assert!(matches!(err, StoreError::Corrupt { .. }));
}
#[test]
fn current_version_passes_through() {
assert_eq!(
Identity.upcast("EffectDone", 1, json!({"a": 1})).unwrap(),
json!({"a": 1})
);
}
#[test]
fn upcasting_is_pure() {
let a = Identity
.upcast("StepStarted", 1, json!({"skill": "x"}))
.unwrap();
let b = Identity
.upcast("StepStarted", 1, json!({"skill": "x"}))
.unwrap();
assert_eq!(a, b);
}
}