1use std::time::Duration;
5
6use tokio::time::Instant;
7
8use crate::behavior::{Address, Behavior, BirthMode, Births};
9use crate::next::Never;
10use crate::protocol::TimerId;
11use crate::shutdown::{FinalizeOnShutdown, ShutdownReaction, StopOnShutdown};
12use crate::stash::{Stash, StashRoute};
13use crate::supervision::{RestartPolicy, Strategy, SupervisionFailureReaction, Supervisor};
14use crate::timing::{Deadline, DeadlineReaction};
15use crate::timing::{ReceiveTimeout, ReceiveTimeoutReaction};
16use crate::watch::{LinkReaction, Watch};
17use crate::{Actions, BehaviorFn, Handler, Machine, Move, Pure, SendAlgebra, delegate_transition};
18
19const DEFAULT_STRATEGY: Strategy = Strategy::OneForOne;
20const DEFAULT_POLICY: RestartPolicy = RestartPolicy::Transient;
21const DEFAULT_BUDGET: (u32, Duration) = (1, Duration::from_secs(5));
22
23fn identity_nonce<N: From<u64>>(index: usize) -> N {
24 N::from(u64::try_from(index).expect("fleet index fits u64"))
25}
26
27pub struct Compose<B> {
28 behavior: B,
29 next_timer: u64,
30}
31
32impl<S: Handler<O, Br, E>, O, Br: BirthMode, E> Compose<Pure<S, O, Br, E>> {
33 #[must_use]
34 pub fn new(state: S) -> Self {
35 Self {
36 behavior: Pure::new(state),
37 next_timer: 0,
38 }
39 }
40}
41
42impl<A, S, M, P, E> Compose<Machine<A, S, M, P, E>>
43where
44 A: Address,
45 P: Copy + PartialEq,
46{
47 #[must_use]
48 pub fn machine(state: S, phase: P, on: fn(P, &mut S, &M) -> Result<Move<P>, E>) -> Self {
49 Self {
50 behavior: Machine::new(state, phase, on),
51 next_timer: 0,
52 }
53 }
54}
55
56impl<S, A, M, Sends, Br, E, I, F> Compose<BehaviorFn<S, A, M, Sends, Br, E, I, F>>
57where
58 A: Address,
59 Sends: SendAlgebra,
60 Br: BirthMode,
61 I: FnMut(&mut S) -> crate::Acted<A, Never, Sends, Br, E>,
62 F: FnMut(&mut S, A, M) -> crate::Acted<A, Never, Sends, Br, E>,
63{
64 #[must_use]
67 pub fn from_fns(state: S, initialize: I, transition: F) -> Self {
68 Self {
69 behavior: BehaviorFn::new(state, initialize, transition),
70 next_timer: 0,
71 }
72 }
73}
74
75impl<B: Behavior> Compose<B> {
76 fn map_behavior<Mapped>(self, map: impl FnOnce(B) -> Mapped) -> Compose<Mapped> {
77 Compose {
78 behavior: map(self.behavior),
79 next_timer: self.next_timer,
80 }
81 }
82
83 fn map_timer<Mapped>(self, map: impl FnOnce(B, TimerId) -> Mapped) -> Compose<Mapped> {
84 let timer = TimerId(self.next_timer);
85 Compose {
86 behavior: map(self.behavior, timer),
87 next_timer: self
88 .next_timer
89 .checked_add(1)
90 .expect("timer identity exhausted"),
91 }
92 }
93
94 #[must_use]
95 pub fn from_behavior(behavior: B) -> Self {
96 Self {
97 behavior,
98 next_timer: 0,
99 }
100 }
101
102 #[must_use]
103 pub fn build(self) -> B {
104 self.behavior
105 }
106
107 #[must_use]
108 pub fn behavior(&self) -> &B {
109 &self.behavior
110 }
111
112 #[must_use]
114 pub fn stop_on_shutdown(self) -> Compose<StopOnShutdown<B>> {
115 self.map_behavior(StopOnShutdown::new)
116 }
117
118 #[must_use]
121 pub fn finalize_on_shutdown(
122 self,
123 finalize: ShutdownReaction<B>,
124 ) -> Compose<FinalizeOnShutdown<B>> {
125 self.map_behavior(|behavior| FinalizeOnShutdown::new(behavior, finalize))
126 }
127
128 #[must_use]
130 pub fn watch(self, peer: B::Addr, on_stopped: LinkReaction<B>) -> Compose<Watch<B>> {
131 self.map_behavior(|behavior| Watch::new(behavior, peer, on_stopped))
132 }
133
134 #[must_use]
141 pub fn deadline(
142 self,
143 when: Option<Instant>,
144 on_reached: DeadlineReaction<B>,
145 ) -> Compose<Deadline<B>> {
146 self.map_timer(|behavior, timer| Deadline::new(behavior, timer, when, on_reached))
147 }
148
149 #[must_use]
162 pub fn receive_timeout(
163 self,
164 after: Duration,
165 on_elapsed: ReceiveTimeoutReaction<B>,
166 ) -> Compose<ReceiveTimeout<B>> {
167 self.map_timer(|behavior, timer| ReceiveTimeout::new(behavior, timer, after, on_elapsed))
168 }
169
170 #[must_use]
172 pub fn stash(self, route: fn(&B::Msg) -> StashRoute) -> Compose<Stash<B>>
173 where
174 B: Behavior<Ph = Never>,
175 {
176 self.map_behavior(|behavior| Stash::new(behavior, route))
177 }
178
179 #[must_use]
182 pub fn children<C>(self, fleet: (usize, fn(usize) -> C)) -> Compose<Supervisor<B, C>>
183 where
184 B: Behavior<Birth = Births<C>>,
185 C: Behavior<Ph = Never, Addr = B::Addr>,
186 <B::Addr as Address>::Nonce: From<u64>,
187 {
188 self.children_with_nonces(identity_nonce, fleet.0, fleet.1)
189 }
190
191 #[must_use]
192 pub fn children_with_nonces<C>(
193 self,
194 nonces: fn(usize) -> <B::Addr as Address>::Nonce,
195 count: usize,
196 build: fn(usize) -> C,
197 ) -> Compose<Supervisor<B, C>>
198 where
199 B: Behavior<Birth = Births<C>>,
200 C: Behavior<Ph = Never, Addr = B::Addr>,
201 {
202 self.map_behavior(|behavior| {
203 Supervisor::new(
204 behavior,
205 nonces,
206 count,
207 build,
208 DEFAULT_STRATEGY,
209 DEFAULT_POLICY,
210 DEFAULT_BUDGET.0,
211 DEFAULT_BUDGET.1,
212 )
213 })
214 }
215}
216
217impl<B, C> Compose<Supervisor<B, C>>
218where
219 B: Behavior<Birth = Births<C>>,
220 C: Behavior<Ph = Never, Addr = B::Addr>,
221{
222 #[must_use]
223 pub fn restart(self, strategy: Strategy) -> Self {
224 Self {
225 behavior: self.behavior.with_strategy(strategy),
226 next_timer: self.next_timer,
227 }
228 }
229
230 #[must_use]
231 pub fn when(self, policy: RestartPolicy) -> Self {
232 Self {
233 behavior: self.behavior.with_policy(policy),
234 next_timer: self.next_timer,
235 }
236 }
237
238 #[must_use]
239 pub fn within(self, maximum: u32, window: Duration) -> Self {
240 Self {
241 behavior: self.behavior.with_budget(maximum, window),
242 next_timer: self.next_timer,
243 }
244 }
245
246 #[must_use]
249 pub fn on_supervision_failure(self, reaction: SupervisionFailureReaction<B>) -> Self {
250 Self {
251 behavior: self.behavior.with_failure_reaction(reaction),
252 next_timer: self.next_timer,
253 }
254 }
255}
256
257impl<B, A, Ph, Sends, Br> Behavior for Compose<B>
258where
259 A: Address,
260 Sends: SendAlgebra,
261 Br: BirthMode,
262 B: Behavior<Addr = A, Ph = Ph, Sends = Sends, Birth = Br>,
263{
264 type Addr = A;
265 type Msg = B::Msg;
266 type Event = B::Event;
267 type Sends = Sends;
268 type Ph = Ph;
269 type Error = B::Error;
270 type Birth = Br;
271
272 fn init(&mut self) -> Result<Actions<A, Ph, Sends, Br>, B::Error> {
273 self.behavior.init()
274 }
275
276 fn transition(&mut self, event: B::Event) -> Result<Actions<A, Ph, Sends, Br>, B::Error> {
277 delegate_transition(&mut self.behavior, event)
278 }
279}