Skip to main content

bombay/runtime/
children.rs

1//! Runtime construction of children emitted by behavior transitions.
2
3use core::future::Future;
4
5use behavior::{Address, BirthMode, Births, Create, Never, NoBirths};
6
7pub(crate) trait SealedChildRuntime {}
8pub(crate) trait SealedBirthMode {}
9
10impl SealedBirthMode for NoBirths {}
11impl<C> SealedBirthMode for Births<C> {}
12
13/// Constructs one child generation and returns its affine ownership lease.
14#[allow(
15    private_bounds,
16    reason = "sealing supertrait is deliberately crate-private"
17)]
18#[doc(hidden)]
19pub trait ChildRuntime<A: Address, B, S>: SealedChildRuntime {
20    /// Fully typed ownership retained by the parent generation.
21    type Lease: super::CoordinatedChild;
22    /// Creation failure.
23    type Error;
24
25    /// Birth `child` beneath `parent` at the emitted nonce.
26    fn birth(
27        &self,
28        parent: A,
29        child: Create<A, B>,
30        response: S,
31    ) -> impl Future<Output = Result<Self::Lease, Self::Error>> + Send;
32}
33
34/// Runtime used when the behavior's birth type is uninhabited.
35#[derive(Debug, Clone, Copy)]
36#[doc(hidden)]
37pub struct NoChildren(());
38
39impl SealedChildRuntime for NoChildren {}
40
41impl NoChildren {
42    pub(crate) const fn new() -> Self {
43        Self(())
44    }
45}
46
47impl<A, S> ChildRuntime<A, Never, S> for NoChildren
48where
49    A: Address + Send,
50    A::Nonce: Send,
51    S: Send,
52{
53    type Lease = Never;
54    type Error = Never;
55
56    async fn birth(
57        &self,
58        _parent: A,
59        child: Create<A, Never>,
60        _response: S,
61    ) -> Result<Self::Lease, Self::Error> {
62        match child.child {}
63    }
64}
65
66/// Derives a generation-local child runtime from a behavior's birth mode.
67#[allow(
68    private_bounds,
69    reason = "sealed birth-mode supertrait is deliberately crate-private"
70)]
71#[doc(hidden)]
72pub trait RuntimeBirthMode<A: Address, Y, S>: BirthMode + SealedBirthMode {
73    /// Runtime constructed for one parent generation.
74    type Runtime: ChildRuntime<A, Self::Child, S>;
75
76    /// Construct an empty runtime for a new parent.
77    fn runtime(system: Y) -> Self::Runtime;
78}
79
80impl<A, Y, S> RuntimeBirthMode<A, Y, S> for NoBirths
81where
82    A: Address + Send,
83    A::Nonce: Send,
84    S: Send,
85{
86    type Runtime = NoChildren;
87
88    fn runtime(_system: Y) -> Self::Runtime {
89        NoChildren::new()
90    }
91}
92
93/// System-backed child runtime derived for `Births<C>`.
94#[doc(hidden)]
95pub struct SystemChildren<Y> {
96    pub(crate) system: Y,
97}
98
99impl<Y> SealedChildRuntime for SystemChildren<Y> {}
100
101impl<A: Address, Y, C, S> RuntimeBirthMode<A, Y, S> for Births<C>
102where
103    SystemChildren<Y>: ChildRuntime<A, C, S>,
104{
105    type Runtime = SystemChildren<Y>;
106
107    fn runtime(system: Y) -> Self::Runtime {
108        SystemChildren { system }
109    }
110}
111
112/// Failure while interpreting a behavior effect.
113#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
114#[doc(hidden)]
115pub enum RuntimeEffectError<C, D> {
116    /// Child birth failed.
117    #[error("child birth failed: {0:?}")]
118    Birth(C),
119    /// A behavior reused a child identity within one parent incarnation.
120    #[error("a behavior reused a child identity within one parent incarnation")]
121    DuplicateChild,
122    /// Outbound delivery failed.
123    #[error("outbound delivery failed: {0:?}")]
124    Delivery(D),
125}
126
127/// Classifies a child-creation failure for same-action rejection delivery.
128///
129/// The interpreter keeps the exact typed error for unobserved creations; this
130/// classification only selects the [`behavior::CreationRejection`] reported to
131/// a behavior that staged an `ObserveCreation` for the failed nonce.
132pub trait CreationFailure {
133    /// The closed semantic classification of this creation failure.
134    fn rejection(&self) -> behavior::CreationRejection;
135}
136
137impl CreationFailure for Never {
138    fn rejection(&self) -> behavior::CreationRejection {
139        match *self {}
140    }
141}