ddd_toolkit_core/event_versioning.rs
1use std::marker::PhantomData;
2
3/// **English:** Event name and schema version supplied by the application.
4/// Fields are public and unvalidated: an empty name or version zero is accepted. Equality compares
5/// both fields. This value supplies no registry, serialization format, or migration dispatch.
6///
7/// **日本語:** アプリケーションが指定するイベント名とスキーマバージョンです。
8/// フィールドは公開され検証されません。空の名前やバージョンゼロも許容します。等値比較は
9/// 両フィールドを比較します。レジストリー、直列化形式、移行の振り分けは提供しません。
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct EventIdentity {
12 /// **English:** Static event name; uniqueness and naming conventions are application-defined.
13 ///
14 /// **日本語:** 静的なイベント名です。一意性と命名規則はアプリケーションが定めます。
15 pub name: &'static str,
16
17 /// **English:** Numeric schema version, with no enforced starting value or ordering policy.
18 ///
19 /// **日本語:** 数値のスキーマバージョンです。開始値や順序の方針は強制しません。
20 pub version: u32,
21}
22
23/// **English:** Type-level event identity independent of any particular event instance.
24/// No [`crate::DomainEvent`] bound is required, and the trait does not validate the returned identity.
25///
26/// **日本語:** 個々のイベントインスタンスとは独立した、型単位のイベント識別情報です。
27/// [`crate::DomainEvent`] の境界は要求せず、返された識別情報も検証しません。
28pub trait VersionedEvent {
29 /// **English:** Returns the name and schema version chosen for this event type.
30 /// Implementations define the mapping; no instance data is passed to this function.
31 ///
32 /// **日本語:** このイベント型に選んだ名前とスキーマバージョンを返します。
33 /// 対応付けは実装が定め、この関数にはインスタンスのデータを渡しません。
34 fn identity() -> EventIdentity;
35}
36
37/// **English:** Fallible owned transformation from an event representation back to the same Rust type.
38/// Versions can be represented inside that type, but checking or advancing them is the
39/// implementation's responsibility. No [`VersionedEvent`] bound or automatic version selection is used.
40///
41/// **日本語:** イベント表現を所有して受け取り、同じ Rust 型へ変換する、失敗し得る操作です。
42/// 型の内部にバージョンを表現できますが、その検査や更新は実装が担います。
43/// [`VersionedEvent`] の境界や自動的なバージョン選択は用いません。
44pub trait EventUpcaster<Event> {
45 /// **English:** Transformation failure forwarded unchanged by [`UpcasterChain::apply`].
46 ///
47 /// **日本語:** [`UpcasterChain::apply`] が変更せず伝播する変換の失敗です。
48 type Error;
49
50 /// **English:** Consumes `event`, returning its transformed representation or an error.
51 /// The input is not returned on error; side effects and panic conditions depend on the upcaster.
52 ///
53 /// **日本語:** `event` を消費し、変換後の表現またはエラーを返します。
54 /// エラー時に入力は返しません。副作用とパニックの条件は変換器に依存します。
55 fn upcast(&self, event: Event) -> Result<Event, Self::Error>;
56}
57
58/// **English:** Insertion-ordered sequence of upcasters of a single concrete type.
59/// Each stage consumes the preceding output. The chain does not select stages by event identity,
60/// sort versions, or restore an event after failure. Use an enum or another common upcaster type
61/// when stages need different behaviors. It stores no event value and adds no locking.
62///
63/// **日本語:** 同じ具体型の変換器を追加順に保持する列です。
64/// 各段階は直前の出力を消費します。イベント識別情報による段階の選択、バージョンの並べ替え、
65/// 失敗後のイベント復元はしません。異なる動作の段階には列挙型などの共通の変換器型を用います。
66/// イベント値は保持せず、ロックも追加しません。
67///
68/// **English:** Add stages explicitly; each successful result becomes the next input.
69///
70/// **日本語:** 段階を明示的に追加すると、各段階の成功結果が次の入力になります。
71///
72/// ```rust
73/// use ddd_toolkit_core::{EventUpcaster, UpcasterChain};
74///
75/// struct Append(&'static str);
76/// impl EventUpcaster<String> for Append {
77/// type Error = std::convert::Infallible;
78/// fn upcast(&self, mut event: String) -> Result<String, Self::Error> {
79/// event.push_str(self.0);
80/// Ok(event)
81/// }
82/// }
83/// let mut chain = UpcasterChain::new();
84/// chain.push(Append("-v2"));
85/// chain.push(Append("-v3"));
86/// assert_eq!(chain.apply(String::from("v1")).unwrap(), "v1-v2-v3");
87/// assert_eq!(chain.len(), 2);
88/// ```
89pub struct UpcasterChain<Event, Upcaster> {
90 upcasters: Vec<Upcaster>,
91 marker: PhantomData<fn() -> Event>,
92}
93
94impl<Event, Upcaster> Default for UpcasterChain<Event, Upcaster> {
95 fn default() -> Self {
96 Self::new()
97 }
98}
99
100impl<Event, Upcaster> UpcasterChain<Event, Upcaster> {
101 /// **English:** Creates an empty chain, also used by [`Default::default`].
102 /// Applying an empty chain returns the input unchanged.
103 ///
104 /// **日本語:** [`Default::default`] でも使う空の列を作ります。
105 /// 空の列を適用すると、入力を変更せず返します。
106 pub fn new() -> Self {
107 Self {
108 upcasters: Vec::new(),
109 marker: PhantomData,
110 }
111 }
112
113 /// **English:** Appends `upcaster` as the last stage without inspecting its version or running it.
114 ///
115 /// **日本語:** バージョンを調べたり実行したりせず、`upcaster` を最後の段階に追加します。
116 pub fn push(&mut self, upcaster: Upcaster) {
117 self.upcasters.push(upcaster);
118 }
119
120 /// **English:** Returns the number of stored stages, not the number of supported event versions.
121 ///
122 /// **日本語:** 対応するイベントバージョン数ではなく、保持する段階数を返します。
123 pub fn len(&self) -> usize {
124 self.upcasters.len()
125 }
126
127 /// **English:** Returns `true` when no upcasters have been added.
128 ///
129 /// **日本語:** 変換器を一つも追加していない場合に `true` を返します。
130 pub fn is_empty(&self) -> bool {
131 self.upcasters.is_empty()
132 }
133
134 /// **English:** Runs all stages in insertion order and returns the final owned event.
135 /// The first error stops evaluation and is returned unchanged; later stages are not called.
136 /// Earlier side effects are not rolled back. An empty chain returns `Ok(event)`.
137 /// Panics from a stage propagate, and the chain itself remains stored for future calls.
138 ///
139 /// **日本語:** 全段階を追加順に実行し、最後の所有されたイベントを返します。
140 /// 最初のエラーで評価を止め、変更せず返します。後続の段階は呼び出しません。
141 /// 先行する副作用は取り消しません。空の列は `Ok(event)` を返します。
142 /// 段階のパニックは伝播し、列自体は後続の呼び出しにも使えるよう保持されます。
143 pub fn apply(&self, mut event: Event) -> Result<Event, Upcaster::Error>
144 where
145 Upcaster: EventUpcaster<Event>,
146 {
147 for upcaster in &self.upcasters {
148 event = upcaster.upcast(event)?;
149 }
150 Ok(event)
151 }
152}