fmodel_rust/
decider.rs

1use crate::{
2    DecideFunction, Decider3, Decider4, Decider5, Decider6, EvolveFunction, InitialStateFunction,
3    Sum, Sum3, Sum4, Sum5, Sum6,
4};
5
6/// [Decider] represents the main decision-making algorithm.
7/// It has three generic parameters `C`/`Command`, `S`/`State`, `E`/`Event` , representing the type of the values that Decider may contain or use.
8/// `'a` is used as a lifetime parameter, indicating that all references contained within the struct (e.g., references within the function closures) must have a lifetime that is at least as long as 'a.
9///
10/// ## Example
11/// ```
12/// use fmodel_rust::decider::{Decider, EventComputation, StateComputation};
13///
14/// fn decider<'a>() -> Decider<'a, OrderCommand, OrderState, OrderEvent> {
15///     Decider {
16///         // Exhaustive pattern matching is used to handle the commands (modeled as Enum - SUM/OR type).
17///         decide: Box::new(|command, state| {
18///            match command {
19///                 OrderCommand::Create(create_cmd) => {
20///                     Ok(vec![OrderEvent::Created(OrderCreatedEvent {
21///                         order_id: create_cmd.order_id,
22///                         customer_name: create_cmd.customer_name.to_owned(),
23///                         items: create_cmd.items.to_owned(),
24///                     })])
25///                 }
26///                 OrderCommand::Update(update_cmd) => {
27///                     if state.order_id == update_cmd.order_id {
28///                         Ok(vec![OrderEvent::Updated(OrderUpdatedEvent {
29///                             order_id: update_cmd.order_id,
30///                             updated_items: update_cmd.new_items.to_owned(),
31///                         })])
32///                     } else {
33///                         Ok(vec![])
34///                     }
35///                 }
36///                 OrderCommand::Cancel(cancel_cmd) => {
37///                     if state.order_id == cancel_cmd.order_id {
38///                         Ok(vec![OrderEvent::Cancelled(OrderCancelledEvent {
39///                             order_id: cancel_cmd.order_id,
40///                         })])
41///                     } else {
42///                         Ok(vec![])
43///                     }
44///                 }
45///             }
46///         }),
47///         // Exhaustive pattern matching is used to handle the events (modeled as Enum - SUM/OR type).
48///         evolve: Box::new(|state, event| {
49///             let mut new_state = state.clone();
50///             match event {
51///                 OrderEvent::Created(created_event) => {
52///                     new_state.order_id = created_event.order_id;
53///                     new_state.customer_name = created_event.customer_name.to_owned();
54///                     new_state.items = created_event.items.to_owned();
55///                 }
56///                 OrderEvent::Updated(updated_event) => {
57///                     new_state.items = updated_event.updated_items.to_owned();
58///                 }
59///                 OrderEvent::Cancelled(_) => {
60///                     new_state.is_cancelled = true;
61///                 }
62///             }
63///             new_state
64///         }),
65///         initial_state: Box::new(|| OrderState {
66///             order_id: 0,
67///             customer_name: "".to_string(),
68///             items: Vec::new(),
69///             is_cancelled: false,
70///         }),
71///     }
72/// }
73///
74/// // Modeling the commands, events, and state. Enum is modeling the SUM/OR type, and struct is modeling the PRODUCT/AND type.
75/// #[derive(Debug)]
76/// pub enum OrderCommand {
77///     Create(CreateOrderCommand),
78///     Update(UpdateOrderCommand),
79///     Cancel(CancelOrderCommand),
80/// }
81///
82/// #[derive(Debug)]
83/// pub struct CreateOrderCommand {
84///     pub order_id: u32,
85///     pub customer_name: String,
86///     pub items: Vec<String>,
87/// }
88///
89/// #[derive(Debug)]
90/// pub struct UpdateOrderCommand {
91///     pub order_id: u32,
92///     pub new_items: Vec<String>,
93/// }
94///
95/// #[derive(Debug)]
96/// pub struct CancelOrderCommand {
97///     pub order_id: u32,
98/// }
99///
100/// #[derive(Debug, PartialEq)]
101/// pub enum OrderEvent {
102///     Created(OrderCreatedEvent),
103///     Updated(OrderUpdatedEvent),
104///     Cancelled(OrderCancelledEvent),
105/// }
106///
107/// #[derive(Debug, PartialEq)]
108/// pub struct OrderCreatedEvent {
109///     pub order_id: u32,
110///     pub customer_name: String,
111///     pub items: Vec<String>,
112/// }
113///
114/// #[derive(Debug, PartialEq)]
115/// pub struct OrderUpdatedEvent {
116///     pub order_id: u32,
117///     pub updated_items: Vec<String>,
118/// }
119///
120/// #[derive(Debug, PartialEq)]
121/// pub struct OrderCancelledEvent {
122///     pub order_id: u32,
123/// }
124///
125/// #[derive(Debug, Clone, PartialEq)]
126/// struct OrderState {
127///     order_id: u32,
128///     customer_name: String,
129///     items: Vec<String>,
130///     is_cancelled: bool,
131/// }
132///
133/// let decider: Decider<OrderCommand, OrderState, OrderEvent> = decider();
134/// let create_order_command = OrderCommand::Create(CreateOrderCommand {
135///     order_id: 1,
136///     customer_name: "John Doe".to_string(),
137///     items: vec!["Item 1".to_string(), "Item 2".to_string()],
138/// });
139/// let new_events = decider.compute_new_events(&[], &create_order_command);
140///     assert_eq!(new_events, Ok(vec![OrderEvent::Created(OrderCreatedEvent {
141///         order_id: 1,
142///         customer_name: "John Doe".to_string(),
143///         items: vec!["Item 1".to_string(), "Item 2".to_string()],
144///     })]));
145///     let new_state = decider.compute_new_state(None, &create_order_command);
146///     assert_eq!(new_state, Ok(OrderState {
147///         order_id: 1,
148///         customer_name: "John Doe".to_string(),
149///         items: vec!["Item 1".to_string(), "Item 2".to_string()],
150///         is_cancelled: false,
151///     }));
152///
153/// ```
154pub struct Decider<'a, C: 'a, S: 'a, E: 'a, Error: 'a = ()> {
155    /// The `decide` function is used to decide which events to produce based on the command and the current state.
156    pub decide: DecideFunction<'a, C, S, E, Error>,
157    /// The `evolve` function is used to evolve the state based on the current state and the event.
158    pub evolve: EvolveFunction<'a, S, E>,
159    /// The `initial_state` function is used to produce the initial state of the decider.
160    pub initial_state: InitialStateFunction<'a, S>,
161}
162
163impl<'a, C, S, E, Error> Decider<'a, C, S, E, Error> {
164    /// Maps the Decider over the S/State type parameter.
165    /// Creates a new instance of [Decider]`<C, S2, E, Error>`.
166    pub fn map_state<S2, F1, F2>(self, f1: &'a F1, f2: &'a F2) -> Decider<'a, C, S2, E, Error>
167    where
168        F1: Fn(&S2) -> S + Send + Sync,
169        F2: Fn(&S) -> S2 + Send + Sync,
170    {
171        let new_decide = Box::new(move |c: &C, s2: &S2| {
172            let s = f1(s2);
173            (self.decide)(c, &s)
174        });
175
176        let new_evolve = Box::new(move |s2: &S2, e: &E| {
177            let s = f1(s2);
178            f2(&(self.evolve)(&s, e))
179        });
180
181        let new_initial_state = Box::new(move || f2(&(self.initial_state)()));
182
183        Decider {
184            decide: new_decide,
185            evolve: new_evolve,
186            initial_state: new_initial_state,
187        }
188    }
189
190    /// Maps the Decider over the E/Event type parameter.
191    /// Creates a new instance of [Decider]`<C, S, E2, Error>`.
192    pub fn map_event<E2, F1, F2>(self, f1: &'a F1, f2: &'a F2) -> Decider<'a, C, S, E2, Error>
193    where
194        F1: Fn(&E2) -> E + Send + Sync,
195        F2: Fn(&E) -> E2 + Send + Sync,
196    {
197        let new_decide = Box::new(move |c: &C, s: &S| {
198            (self.decide)(c, s).map(|result| result.into_iter().map(|e: E| f2(&e)).collect())
199        });
200
201        let new_evolve = Box::new(move |s: &S, e2: &E2| {
202            let e = f1(e2);
203            (self.evolve)(s, &e)
204        });
205
206        let new_initial_state = Box::new(move || (self.initial_state)());
207
208        Decider {
209            decide: new_decide,
210            evolve: new_evolve,
211            initial_state: new_initial_state,
212        }
213    }
214
215    /// Maps the Decider over the C/Command type parameter.
216    /// Creates a new instance of [Decider]`<C2, S, E, Error>`.
217    pub fn map_command<C2, F>(self, f: &'a F) -> Decider<'a, C2, S, E, Error>
218    where
219        F: Fn(&C2) -> C + Send + Sync,
220    {
221        let new_decide = Box::new(move |c2: &C2, s: &S| {
222            let c = f(c2);
223            (self.decide)(&c, s)
224        });
225
226        let new_evolve = Box::new(move |s: &S, e: &E| (self.evolve)(s, e));
227
228        let new_initial_state = Box::new(move || (self.initial_state)());
229
230        Decider {
231            decide: new_decide,
232            evolve: new_evolve,
233            initial_state: new_initial_state,
234        }
235    }
236
237    /// Maps the Decider over the Error type parameter.
238    /// Creates a new instance of [Decider]`<C, S, E, Error2>`.
239    pub fn map_error<Error2, F>(self, f: &'a F) -> Decider<'a, C, S, E, Error2>
240    where
241        F: Fn(&Error) -> Error2 + Send + Sync,
242    {
243        let new_decide = Box::new(move |c: &C, s: &S| (self.decide)(c, s).map_err(|e| f(&e)));
244
245        let new_evolve = Box::new(move |s: &S, e: &E| (self.evolve)(s, e));
246
247        let new_initial_state = Box::new(move || (self.initial_state)());
248
249        Decider {
250            decide: new_decide,
251            evolve: new_evolve,
252            initial_state: new_initial_state,
253        }
254    }
255
256    /// Combines two deciders into one bigger decider
257    /// Creates a new instance of a Decider by combining two deciders of type `C`, `S`, `E` and `C2`, `S2`, `E2` into a new decider of type `Sum<C, C2>`, `(S, S2)`, `Sum<E, E2>`
258    #[allow(clippy::type_complexity)]
259    pub fn combine<C2, S2, E2>(
260        self,
261        decider2: Decider<'a, C2, S2, E2, Error>,
262    ) -> Decider<'a, Sum<C, C2>, (S, S2), Sum<E, E2>, Error>
263    where
264        S: Clone,
265        S2: Clone,
266    {
267        let new_decide = Box::new(move |c: &Sum<C, C2>, s: &(S, S2)| match c {
268            Sum::First(c) => {
269                let s1 = &s.0;
270                let events = (self.decide)(c, s1);
271                events.map(|result| {
272                    result
273                        .into_iter()
274                        .map(|e: E| Sum::First(e))
275                        .collect::<Vec<Sum<E, E2>>>()
276                })
277            }
278            Sum::Second(c) => {
279                let s2 = &s.1;
280                let events = (decider2.decide)(c, s2);
281                events.map(|result| {
282                    result
283                        .into_iter()
284                        .map(|e: E2| Sum::Second(e))
285                        .collect::<Vec<Sum<E, E2>>>()
286                })
287            }
288        });
289
290        let new_evolve = Box::new(move |s: &(S, S2), e: &Sum<E, E2>| match e {
291            Sum::First(e) => {
292                let s1 = &s.0;
293                let new_state = (self.evolve)(s1, e);
294                (new_state, s.1.to_owned())
295            }
296            Sum::Second(e) => {
297                let s2 = &s.1;
298                let new_state = (decider2.evolve)(s2, e);
299                (s.0.to_owned(), new_state)
300            }
301        });
302
303        let new_initial_state = Box::new(move || {
304            let s1 = (self.initial_state)();
305            let s2 = (decider2.initial_state)();
306            (s1, s2)
307        });
308
309        Decider {
310            decide: new_decide,
311            evolve: new_evolve,
312            initial_state: new_initial_state,
313        }
314    }
315
316    /// Combines three deciders into one bigger decider
317    pub fn combine3<C2, S2, E2, C3, S3, E3>(
318        self,
319        decider2: Decider<'a, C2, S2, E2, Error>,
320        decider3: Decider<'a, C3, S3, E3, Error>,
321    ) -> Decider3<'a, C, C2, C3, S, S2, S3, E, E2, E3, Error>
322    where
323        S: Clone,
324        S2: Clone,
325        S3: Clone,
326        E: Clone,
327        E2: Clone,
328        E3: Clone,
329        C: Clone,
330        C2: Clone,
331        C3: Clone,
332    {
333        // First combine self with decider2
334        let combined = self.combine(decider2);
335
336        // Then combine with decider3 and map the types
337        combined
338            .combine(decider3)
339            .map_state(
340                &|s: &(S, S2, S3)| ((s.0.clone(), s.1.clone()), s.2.clone()),
341                &|s: &((S, S2), S3)| (s.0 .0.clone(), s.0 .1.clone(), s.1.clone()),
342            )
343            .map_event(
344                &|e: &Sum3<E, E2, E3>| match e {
345                    Sum3::First(ref e) => Sum::First(Sum::First(e.clone())),
346                    Sum3::Second(ref e) => Sum::First(Sum::Second(e.clone())),
347                    Sum3::Third(ref e) => Sum::Second(e.clone()),
348                },
349                &|e| match e {
350                    Sum::First(Sum::First(e)) => Sum3::First(e.clone()),
351                    Sum::First(Sum::Second(e)) => Sum3::Second(e.clone()),
352                    Sum::Second(e) => Sum3::Third(e.clone()),
353                },
354            )
355            .map_command(&|c: &Sum3<C, C2, C3>| match c {
356                Sum3::First(c) => Sum::First(Sum::First(c.clone())),
357                Sum3::Second(c) => Sum::First(Sum::Second(c.clone())),
358                Sum3::Third(c) => Sum::Second(c.clone()),
359            })
360    }
361
362    #[allow(clippy::type_complexity)]
363    /// Combines four deciders into one bigger decider
364    pub fn combine4<C2, S2, E2, C3, S3, E3, C4, S4, E4>(
365        self,
366        decider2: Decider<'a, C2, S2, E2, Error>,
367        decider3: Decider<'a, C3, S3, E3, Error>,
368        decider4: Decider<'a, C4, S4, E4, Error>,
369    ) -> Decider4<'a, C, C2, C3, C4, S, S2, S3, S4, E, E2, E3, E4, Error>
370    where
371        S: Clone,
372        S2: Clone,
373        S3: Clone,
374        S4: Clone,
375        E: Clone,
376        E2: Clone,
377        E3: Clone,
378        E4: Clone,
379        C: Clone,
380        C2: Clone,
381        C3: Clone,
382        C4: Clone,
383    {
384        let combined = self
385            .combine(decider2)
386            .combine(decider3)
387            .combine(decider4)
388            .map_state(
389                &|s: &(S, S2, S3, S4)| (((s.0.clone(), s.1.clone()), s.2.clone()), s.3.clone()),
390                &|s: &(((S, S2), S3), S4)| {
391                    (
392                        s.0 .0 .0.clone(),
393                        s.0 .0 .1.clone(),
394                        s.0 .1.clone(),
395                        s.1.clone(),
396                    )
397                },
398            )
399            .map_event(
400                &|e: &Sum4<E, E2, E3, E4>| match e {
401                    Sum4::First(e) => Sum::First(Sum::First(Sum::First(e.clone()))),
402                    Sum4::Second(e) => Sum::First(Sum::First(Sum::Second(e.clone()))),
403                    Sum4::Third(e) => Sum::First(Sum::Second(e.clone())),
404                    Sum4::Fourth(e) => Sum::Second(e.clone()),
405                },
406                &|e| match e {
407                    Sum::First(Sum::First(Sum::First(e))) => Sum4::First(e.clone()),
408                    Sum::First(Sum::First(Sum::Second(e))) => Sum4::Second(e.clone()),
409                    Sum::First(Sum::Second(e)) => Sum4::Third(e.clone()),
410                    Sum::Second(e) => Sum4::Fourth(e.clone()),
411                },
412            )
413            .map_command(&|c: &Sum4<C, C2, C3, C4>| match c {
414                Sum4::First(c) => Sum::First(Sum::First(Sum::First(c.clone()))),
415                Sum4::Second(c) => Sum::First(Sum::First(Sum::Second(c.clone()))),
416                Sum4::Third(c) => Sum::First(Sum::Second(c.clone())),
417                Sum4::Fourth(c) => Sum::Second(c.clone()),
418            });
419        combined
420    }
421
422    #[allow(clippy::type_complexity)]
423    /// Combines five deciders into one bigger decider
424    pub fn combine5<C2, S2, E2, C3, S3, E3, C4, S4, E4, C5, S5, E5>(
425        self,
426        decider2: Decider<'a, C2, S2, E2, Error>,
427        decider3: Decider<'a, C3, S3, E3, Error>,
428        decider4: Decider<'a, C4, S4, E4, Error>,
429        decider5: Decider<'a, C5, S5, E5, Error>,
430    ) -> Decider5<'a, C, C2, C3, C4, C5, S, S2, S3, S4, S5, E, E2, E3, E4, E5, Error>
431    where
432        S: Clone,
433        S2: Clone,
434        S3: Clone,
435        S4: Clone,
436        S5: Clone,
437        E: Clone,
438        E2: Clone,
439        E3: Clone,
440        E4: Clone,
441        E5: Clone,
442        C: Clone,
443        C2: Clone,
444        C3: Clone,
445        C4: Clone,
446        C5: Clone,
447    {
448        let combined = self
449            .combine(decider2)
450            .combine(decider3)
451            .combine(decider4)
452            .combine(decider5)
453            .map_state(
454                &|s: &(S, S2, S3, S4, S5)| {
455                    (
456                        (((s.0.clone(), s.1.clone()), s.2.clone()), s.3.clone()),
457                        s.4.clone(),
458                    )
459                },
460                &|s: &((((S, S2), S3), S4), S5)| {
461                    (
462                        s.0 .0 .0 .0.clone(),
463                        s.0 .0 .0 .1.clone(),
464                        s.0 .0 .1.clone(),
465                        s.0 .1.clone(),
466                        s.1.clone(),
467                    )
468                },
469            )
470            .map_event(
471                &|e: &Sum5<E, E2, E3, E4, E5>| match e {
472                    Sum5::First(e) => Sum::First(Sum::First(Sum::First(Sum::First(e.clone())))),
473                    Sum5::Second(e) => Sum::First(Sum::First(Sum::First(Sum::Second(e.clone())))),
474                    Sum5::Third(e) => Sum::First(Sum::First(Sum::Second(e.clone()))),
475                    Sum5::Fourth(e) => Sum::First(Sum::Second(e.clone())),
476                    Sum5::Fifth(e) => Sum::Second(e.clone()),
477                },
478                &|e| match e {
479                    Sum::First(Sum::First(Sum::First(Sum::First(e)))) => Sum5::First(e.clone()),
480                    Sum::First(Sum::First(Sum::First(Sum::Second(e)))) => Sum5::Second(e.clone()),
481                    Sum::First(Sum::First(Sum::Second(e))) => Sum5::Third(e.clone()),
482                    Sum::First(Sum::Second(e)) => Sum5::Fourth(e.clone()),
483                    Sum::Second(e) => Sum5::Fifth(e.clone()),
484                },
485            )
486            .map_command(&|c: &Sum5<C, C2, C3, C4, C5>| match c {
487                Sum5::First(c) => Sum::First(Sum::First(Sum::First(Sum::First(c.clone())))),
488                Sum5::Second(c) => Sum::First(Sum::First(Sum::First(Sum::Second(c.clone())))),
489                Sum5::Third(c) => Sum::First(Sum::First(Sum::Second(c.clone()))),
490                Sum5::Fourth(c) => Sum::First(Sum::Second(c.clone())),
491                Sum5::Fifth(c) => Sum::Second(c.clone()),
492            });
493        combined
494    }
495
496    #[allow(clippy::type_complexity)]
497    /// Combines six deciders into one bigger decider
498    pub fn combine6<C2, S2, E2, C3, S3, E3, C4, S4, E4, C5, S5, E5, C6, S6, E6>(
499        self,
500        decider2: Decider<'a, C2, S2, E2, Error>,
501        decider3: Decider<'a, C3, S3, E3, Error>,
502        decider4: Decider<'a, C4, S4, E4, Error>,
503        decider5: Decider<'a, C5, S5, E5, Error>,
504        decider6: Decider<'a, C6, S6, E6, Error>,
505    ) -> Decider6<'a, C, C2, C3, C4, C5, C6, S, S2, S3, S4, S5, S6, E, E2, E3, E4, E5, E6, Error>
506    where
507        S: Clone,
508        S2: Clone,
509        S3: Clone,
510        S4: Clone,
511        S5: Clone,
512        S6: Clone,
513        E: Clone,
514        E2: Clone,
515        E3: Clone,
516        E4: Clone,
517        E5: Clone,
518        E6: Clone,
519        C: Clone,
520        C2: Clone,
521        C3: Clone,
522        C4: Clone,
523        C5: Clone,
524        C6: Clone,
525    {
526        let combined = self
527            .combine(decider2)
528            .combine(decider3)
529            .combine(decider4)
530            .combine(decider5)
531            .combine(decider6)
532            .map_state(
533                &|s: &(S, S2, S3, S4, S5, S6)| {
534                    (
535                        (
536                            (((s.0.clone(), s.1.clone()), s.2.clone()), s.3.clone()),
537                            s.4.clone(),
538                        ),
539                        s.5.clone(),
540                    )
541                },
542                &|s: &(((((S, S2), S3), S4), S5), S6)| {
543                    (
544                        s.0 .0 .0 .0 .0.clone(),
545                        s.0 .0 .0 .0 .1.clone(),
546                        s.0 .0 .0 .1.clone(),
547                        s.0 .0 .1.clone(),
548                        s.0 .1.clone(),
549                        s.1.clone(),
550                    )
551                },
552            )
553            .map_event(
554                &|e: &Sum6<E, E2, E3, E4, E5, E6>| match e {
555                    Sum6::First(e) => {
556                        Sum::First(Sum::First(Sum::First(Sum::First(Sum::First(e.clone())))))
557                    }
558                    Sum6::Second(e) => {
559                        Sum::First(Sum::First(Sum::First(Sum::First(Sum::Second(e.clone())))))
560                    }
561                    Sum6::Third(e) => Sum::First(Sum::First(Sum::First(Sum::Second(e.clone())))),
562                    Sum6::Fourth(e) => Sum::First(Sum::First(Sum::Second(e.clone()))),
563                    Sum6::Fifth(e) => Sum::First(Sum::Second(e.clone())),
564                    Sum6::Sixth(e) => Sum::Second(e.clone()),
565                },
566                &|e| match e {
567                    Sum::First(Sum::First(Sum::First(Sum::First(Sum::First(e))))) => {
568                        Sum6::First(e.clone())
569                    }
570                    Sum::First(Sum::First(Sum::First(Sum::First(Sum::Second(e))))) => {
571                        Sum6::Second(e.clone())
572                    }
573                    Sum::First(Sum::First(Sum::First(Sum::Second(e)))) => Sum6::Third(e.clone()),
574                    Sum::First(Sum::First(Sum::Second(e))) => Sum6::Fourth(e.clone()),
575                    Sum::First(Sum::Second(e)) => Sum6::Fifth(e.clone()),
576                    Sum::Second(e) => Sum6::Sixth(e.clone()),
577                },
578            )
579            .map_command(&|c: &Sum6<C, C2, C3, C4, C5, C6>| match c {
580                Sum6::First(c) => {
581                    Sum::First(Sum::First(Sum::First(Sum::First(Sum::First(c.clone())))))
582                }
583                Sum6::Second(c) => {
584                    Sum::First(Sum::First(Sum::First(Sum::First(Sum::Second(c.clone())))))
585                }
586                Sum6::Third(c) => Sum::First(Sum::First(Sum::First(Sum::Second(c.clone())))),
587                Sum6::Fourth(c) => Sum::First(Sum::First(Sum::Second(c.clone()))),
588                Sum6::Fifth(c) => Sum::First(Sum::Second(c.clone())),
589                Sum6::Sixth(c) => Sum::Second(c.clone()),
590            });
591        combined
592    }
593}
594
595/// Formalizes the `Event Computation` algorithm / event sourced system for the `decider` to handle commands based on the current events, and produce new events.
596pub trait EventComputation<C, S, E, Error = ()> {
597    /// Computes new events based on the current events and the command.
598    fn compute_new_events(&self, current_events: &[E], command: &C) -> Result<Vec<E>, Error>;
599}
600
601/// Formalizes the `State Computation` algorithm / state-stored system for the `decider` to handle commands based on the current state, and produce new state.
602pub trait StateComputation<C, S, E, Error = ()> {
603    /// Computes new state based on the current state and the command.
604    fn compute_new_state(&self, current_state: Option<S>, command: &C) -> Result<S, Error>;
605}
606
607impl<C, S, E, Error> EventComputation<C, S, E, Error> for Decider<'_, C, S, E, Error> {
608    /// Computes new events based on the current events and the command.
609    fn compute_new_events(&self, current_events: &[E], command: &C) -> Result<Vec<E>, Error> {
610        let current_state: S = current_events
611            .iter()
612            .fold((self.initial_state)(), |state, event| {
613                (self.evolve)(&state, event)
614            });
615        (self.decide)(command, &current_state)
616    }
617}
618
619impl<C, S, E, Error> StateComputation<C, S, E, Error> for Decider<'_, C, S, E, Error> {
620    /// Computes new state based on the current state and the command.
621    fn compute_new_state(&self, current_state: Option<S>, command: &C) -> Result<S, Error> {
622        let effective_current_state = current_state.unwrap_or_else(|| (self.initial_state)());
623        let events = (self.decide)(command, &effective_current_state);
624        events.map(|result| {
625            result
626                .into_iter()
627                .fold(effective_current_state, |state, event| {
628                    (self.evolve)(&state, &event)
629                })
630        })
631    }
632}