1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::ops::{Add, AddAssign};
use crate::{action::Action, message::Message};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StateChanged {
Unchanged,
MaybeChanged,
}
impl Add<StateChanged> for StateChanged {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Self::Unchanged, Self::Unchanged) => Self::Unchanged,
(_, _) => Self::MaybeChanged,
}
}
}
impl AddAssign for StateChanged {
fn add_assign(&mut self, other: Self) {
*self = *self + other;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StateUpdated<Effect, Task> {
pub changed: StateChanged,
pub next_action: Option<Action<Effect, Task>>,
}
impl<Effect, Task> StateUpdated<Effect, Task> {
pub fn unchanged(next_action: impl Into<Option<Action<Effect, Task>>>) -> Self {
Self {
changed: StateChanged::Unchanged,
next_action: next_action.into(),
}
}
pub fn maybe_changed(next_action: impl Into<Option<Action<Effect, Task>>>) -> Self {
Self {
changed: StateChanged::MaybeChanged,
next_action: next_action.into(),
}
}
}
pub fn state_updated<E1, E2, T1, T2>(from: StateUpdated<E1, T1>) -> StateUpdated<E2, T2>
where
E1: Into<E2>,
T1: Into<T2>,
{
let StateUpdated {
changed,
next_action,
} = from;
let next_action = next_action.map(|action| match action {
Action::ApplyEffect(effect) => Action::apply_effect(effect),
Action::DispatchTask(task) => Action::dispatch_task(task),
});
StateUpdated {
changed,
next_action,
}
}
pub trait State {
type Intent;
type Effect;
type Task;
fn update(
&mut self,
message: Message<Self::Intent, Self::Effect>,
) -> StateUpdated<Self::Effect, Self::Task>;
}
pub type RenderStateFn<State, Intent> = dyn FnMut(&State) -> Option<Intent> + Send;