fmodel_rust/
decider.rs

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