1use core::future::Future;
4use core::marker::PhantomData;
5
6use super::addressing::Address;
7use crate::next::Never;
8use crate::{Behavior, Protocol};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum CreationKind<N> {
13 Birth,
15 ReplacementIncarnation {
17 replaces: N,
19 },
20}
21
22impl<N> CreationKind<N> {
23 #[must_use]
24 pub const fn replacement_of(replaces: N) -> Self {
25 Self::ReplacementIncarnation { replaces }
26 }
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct Create<A: Address, New> {
38 pub nonce: A::Nonce,
39 pub child: New,
40 pub kind: CreationKind<A::Nonce>,
41}
42
43impl<A: Address, New> Create<A, New> {
44 #[must_use]
45 pub const fn new(nonce: A::Nonce, child: New, kind: CreationKind<A::Nonce>) -> Self {
46 Self { nonce, child, kind }
47 }
48
49 #[must_use]
50 pub const fn birth(nonce: A::Nonce, child: New) -> Self {
51 Self::new(nonce, child, CreationKind::Birth)
52 }
53
54 #[must_use]
55 pub const fn replacement_incarnation(nonce: A::Nonce, replaces: A::Nonce, child: New) -> Self {
56 Self::new(nonce, child, CreationKind::replacement_of(replaces))
57 }
58}
59
60pub trait InstallBirth<A: Address, C: Behavior, Output, Error>
69where
70 C::Protocol: Protocol<Addr = A>,
71{
72 fn install_birth(
78 &mut self,
79 creation: Create<A, C>,
80 ) -> impl Future<Output = Result<Output, Error>> + Send;
81}
82
83pub trait DispatchBirth<A: Address, Installer, Output, Error>: Sized {
92 fn dispatch_birth(
97 self,
98 nonce: A::Nonce,
99 kind: CreationKind<A::Nonce>,
100 installer: &mut Installer,
101 ) -> impl Future<Output = Result<Output, Error>> + Send;
102}
103
104#[derive(Debug, Clone, PartialEq, Eq)]
163pub enum ChildChoice<Head, Tail> {
164 Head(Head),
166 Tail(Tail),
168}
169
170mod sealed {
171 pub trait ChildProduct {}
172}
173
174#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
176pub struct NoChildren;
177
178impl sealed::ChildProduct for NoChildren {}
179
180pub struct ChildCons<A: Address, C, Earlier> {
182 creation: Create<A, C>,
183 earlier: Earlier,
184}
185
186impl<A: Address, C, Earlier> sealed::ChildProduct for ChildCons<A, C, Earlier> {}
187
188pub struct Children<A: Address, Product = NoChildren> {
195 product: Product,
196 address: PhantomData<fn() -> A>,
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
201pub enum ChildrenError<N> {
202 #[error("duplicate creator-local child nonce")]
204 DuplicateNonce {
205 nonce: N,
207 },
208}
209
210pub trait ChildProduct<A: Address>: sealed::ChildProduct + Sized {
212 type Choice;
214
215 #[doc(hidden)]
216 fn stage(
217 self,
218 ) -> Result<(Vec<Create<A, Self::Choice>>, Vec<A::Nonce>), ChildrenError<A::Nonce>>;
219}
220
221impl<A: Address> ChildProduct<A> for NoChildren {
222 type Choice = Never;
223
224 fn stage(
225 self,
226 ) -> Result<(Vec<Create<A, Self::Choice>>, Vec<A::Nonce>), ChildrenError<A::Nonce>> {
227 Ok((Vec::new(), Vec::new()))
228 }
229}
230
231impl<A, C, Earlier> ChildProduct<A> for ChildCons<A, C, Earlier>
232where
233 A: Address,
234 C: Behavior,
235 C::Protocol: Protocol<Addr = A>,
236 Earlier: ChildProduct<A>,
237{
238 type Choice = ChildChoice<C, Earlier::Choice>;
239
240 fn stage(
241 self,
242 ) -> Result<(Vec<Create<A, Self::Choice>>, Vec<A::Nonce>), ChildrenError<A::Nonce>> {
243 let (earlier, mut nonces) = self.earlier.stage()?;
244 if nonces.contains(&self.creation.nonce) {
245 return Err(ChildrenError::DuplicateNonce {
246 nonce: self.creation.nonce,
247 });
248 }
249 let mut creates = earlier
250 .into_iter()
251 .map(|creation| {
252 Create::new(
253 creation.nonce,
254 ChildChoice::Tail(creation.child),
255 creation.kind,
256 )
257 })
258 .collect::<Vec<_>>();
259 nonces.push(self.creation.nonce);
260 creates.push(Create::new(
261 self.creation.nonce,
262 ChildChoice::Head(self.creation.child),
263 self.creation.kind,
264 ));
265 Ok((creates, nonces))
266 }
267}
268
269impl<A: Address> Children<A, NoChildren> {
270 #[must_use]
272 pub const fn new() -> Self {
273 Self {
274 product: NoChildren,
275 address: PhantomData,
276 }
277 }
278}
279
280impl<A: Address> Default for Children<A, NoChildren> {
281 fn default() -> Self {
282 Self::new()
283 }
284}
285
286impl<A: Address, Product> Children<A, Product> {
287 #[must_use]
289 pub fn create<C>(self, creation: Create<A, C>) -> Children<A, ChildCons<A, C, Product>>
290 where
291 C: Behavior,
292 C::Protocol: Protocol<Addr = A>,
293 {
294 Children {
295 product: ChildCons {
296 creation,
297 earlier: self.product,
298 },
299 address: PhantomData,
300 }
301 }
302
303 #[must_use]
305 pub fn child<C>(self, nonce: A::Nonce, child: C) -> Children<A, ChildCons<A, C, Product>>
306 where
307 C: Behavior,
308 C::Protocol: Protocol<Addr = A>,
309 {
310 self.create(Create::birth(nonce, child))
311 }
312}
313
314impl<A, Product> Children<A, Product>
315where
316 A: Address,
317 Product: ChildProduct<A>,
318{
319 pub fn into_creates(self) -> Result<Vec<Create<A, Product::Choice>>, ChildrenError<A::Nonce>> {
327 self.product.stage().map(|(creates, _)| creates)
328 }
329}
330
331impl<A, Head, Tail, Installer, Output, Error> DispatchBirth<A, Installer, Output, Error>
332 for ChildChoice<Head, Tail>
333where
334 A: Address,
335 A::Nonce: Send,
336 Head: Behavior + Send,
337 Head::Protocol: Protocol<Addr = A>,
338 Tail: DispatchBirth<A, Installer, Output, Error> + Send,
339 Installer: InstallBirth<A, Head, Output, Error> + Send,
340{
341 async fn dispatch_birth(
342 self,
343 nonce: A::Nonce,
344 kind: CreationKind<A::Nonce>,
345 installer: &mut Installer,
346 ) -> Result<Output, Error> {
347 match self {
348 Self::Head(child) => {
349 installer
350 .install_birth(Create::new(nonce, child, kind))
351 .await
352 }
353 Self::Tail(tail) => tail.dispatch_birth(nonce, kind, installer).await,
354 }
355 }
356}
357
358impl<A, Installer, Output, Error> DispatchBirth<A, Installer, Output, Error> for Never
359where
360 A: Address,
361{
362 fn dispatch_birth(
363 self,
364 _nonce: A::Nonce,
365 _kind: CreationKind<A::Nonce>,
366 _installer: &mut Installer,
367 ) -> impl Future<Output = Result<Output, Error>> + Send {
368 async move { match self {} }
369 }
370}
371
372impl<A, C, Installer, Output, Error> DispatchBirth<A, Installer, Output, Error> for C
373where
374 A: Address,
375 C: Behavior,
376 C::Protocol: Protocol<Addr = A>,
377 Installer: InstallBirth<A, C, Output, Error>,
378{
379 fn dispatch_birth(
380 self,
381 nonce: A::Nonce,
382 kind: CreationKind<A::Nonce>,
383 installer: &mut Installer,
384 ) -> impl Future<Output = Result<Output, Error>> + Send {
385 installer.install_birth(Create::new(nonce, self, kind))
386 }
387}
388
389pub trait BirthMode {
391 type Child;
392}
393
394#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
396pub struct NoBirths;
397
398impl BirthMode for NoBirths {
399 type Child = Never;
400}
401
402#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
404pub struct Births<C>(PhantomData<fn() -> C>);
405
406impl<C> BirthMode for Births<C> {
407 type Child = C;
408}
409
410#[cfg(test)]
411mod tests {
412 use super::*;
413 use crate::{Actions, BehaviorActed, MailAddr, NoBirths, User};
414
415 struct Child;
416
417 impl behavior::Protocol for Child {
418 type Addr = MailAddr;
419 type Msg = u8;
420 }
421
422 impl Behavior for Child {
423 type Protocol = Self;
424 type Event = User<MailAddr, u8>;
425 type Sends = Vec<Never>;
426 type Ph = Never;
427 type Error = Never;
428 type Birth = NoBirths;
429
430 fn transition(&mut self, _: crate::ActiveTurn, _: Self::Event) -> BehaviorActed<Self> {
431 Ok(Actions::cont())
432 }
433 }
434
435 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
436 enum InstallError {
437 Refused,
438 }
439
440 struct RecordingInstaller {
441 calls: usize,
442 observed: Vec<(u64, CreationKind<u64>)>,
443 result: Result<u32, InstallError>,
444 }
445
446 impl InstallBirth<MailAddr, Child, u32, InstallError> for RecordingInstaller {
447 async fn install_birth(
448 &mut self,
449 creation: Create<MailAddr, Child>,
450 ) -> Result<u32, InstallError> {
451 self.calls += 1;
452 self.observed.push((creation.nonce, creation.kind));
453 self.result
454 }
455 }
456
457 fn installer(result: Result<u32, InstallError>) -> RecordingInstaller {
458 RecordingInstaller {
459 calls: 0,
460 observed: Vec::new(),
461 result,
462 }
463 }
464
465 fn assert_send<T: Send>(_: &T) {}
466
467 #[test]
468 fn empty_child_product_stages_no_creations_or_nonces() {
469 let (creations, nonces) = <NoChildren as ChildProduct<MailAddr>>::stage(NoChildren)
470 .expect("an empty child product is valid");
471 assert!(creations.is_empty());
472 assert!(nonces.is_empty());
473 }
474
475 #[tokio::test]
476 async fn concrete_child_dispatches_once_with_exact_nonce_provenance_and_output() {
477 let mut installer = installer(Ok(91));
478 let future = Child.dispatch_birth(
479 17,
480 CreationKind::ReplacementIncarnation { replaces: 8 },
481 &mut installer,
482 );
483 assert_send(&future);
484 let result = future.await;
485
486 assert_eq!(result, Ok(91));
487 assert_eq!(installer.calls, 1);
488 assert_eq!(
489 installer.observed,
490 [(17, CreationKind::ReplacementIncarnation { replaces: 8 })]
491 );
492 }
493
494 #[tokio::test]
495 async fn concrete_child_returns_the_exact_installer_error_without_retry() {
496 let mut installer = installer(Err(InstallError::Refused));
497 let future = Child.dispatch_birth(23, CreationKind::replacement_of(19), &mut installer);
498 assert_send(&future);
499 let result = future.await;
500
501 assert_eq!(result, Err(InstallError::Refused));
502 assert_eq!(installer.calls, 1);
503 assert_eq!(installer.observed, [(23, CreationKind::replacement_of(19))]);
504 }
505}