fmodel_rust/
decider.rs

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