behavior/lib.rs
1//! Pure, typed actor-behavior primitives.
2//!
3//! [`Protocol`] is stable public destination identity (`Addr` plus `Msg`). A
4//! [`Behavior`] separately owns state and folds its complete [`Behavior::Event`]
5//! algebra into exactly [`Actions`]: sends, fresh creations, and its next
6//! behavior or termination. A protocol is not a behavior, and `Behavior` is not
7//! a `Protocol` supertrait. Higher capabilities extend internal event and
8//! effect algebras while transparent wrappers preserve [`Behavior::Protocol`].
9//!
10//! Finite mailbox execution belongs to a runtime or test driver, not to this
11//! one-turn behavior algebra.
12//!
13//! ```compile_fail
14//! use behavior::ActionReducer;
15//! ```
16
17// The `#[behavior]` expansion emits `::behavior::…` paths; this alias lets the
18// expansion resolve inside this crate too.
19extern crate self as behavior;
20
21mod actor;
22mod effect;
23mod effects;
24mod next;
25mod transition;
26mod user_event;
27
28pub use actor::{
29 Address, AllocationRejection, BirthMode, BirthNodeAppend, BirthNodeAt, BirthNodeLogicalHosts,
30 BirthNodeProtocols, BirthProtocol, BirthProtocolAt, BirthProtocolHead, BirthProtocolProduct,
31 BirthProtocolTail, BirthProtocols, Births, ChildChoice, ChildCons, ChildCreationOutcome,
32 ChildCreationProduct, ChildCreationSettled, ChildDelivery, ChildDeliveryReason, ChildHead,
33 ChildInput, ChildInputReason, ChildNamespaceExhausted, ChildOccurrence, ChildOccurrenceProduct,
34 ChildOccurrenceProductAt, ChildOccurrenceResolution, ChildOccurrenceShape, ChildOccurrences,
35 ChildPosition, ChildProduct, ChildReport, ChildRole, ChildTail, Children, CreateChild,
36 CreationCorrelation, CreationId, CreationKind, CreationRejection, CreationSequence, Creations,
37 DeclaredChildOccurrence, Delivery, DispatchBirth, EndpointAddress, EstablishChild,
38 EstablishedActor, EstablishedCreation, EstablishedDelivery, EstablishedRecipient,
39 ExactDeliveryReason, InterpretEstablished, LogicalDeliveryReason, MailAddr, NoBirthProtocols,
40 NoBirths, NoChildren, Recipient, ResolveChildOccurrence, ResolvedChild, ResolvedChildPosition,
41 RoleChild, RoleProtocol, RoutedCreation, StructuralChildOccurrence,
42};
43pub use effect::Effect;
44pub use effects::{
45 Acted, ActionItem, ActionItemResult, ActionSettlement, ActionSettlements, Actions, AppendSend,
46 Become, ClassifySettlement, CreationCustody, CreationSettlement, CreationSettlements,
47 CreationsSettled, InterpretCreations, InterpretItem, InterpretSends, Interpretation,
48 InterpreterFault, InterpreterRequest, InterpreterRequests, ItemSettlement,
49 LogicalDeliveryProtocols, NoReturnToEmitter, NoSends, Own, ParentReportReason, ReportToParent,
50 ReturnsToEmitter, SendEffects, SendInput, SendLayer, SendSettlements, SendsFor, SettledItem,
51 SettlementStatus, SourceAction, SourceActions, SourceAdmission, SourceCustody,
52 SourceSettlementCustody, SourceSettlements, settle_in_order, settle_item,
53};
54pub use next::{Never, Step, Stopped};
55pub use transition::{
56 ActiveTurn, Behavior, BehaviorActed, BehaviorAddr, BehaviorBase, BehaviorLayer,
57 BehaviorMessage, InitializationTurn, LogicalHostRequirements, MessageProtocol, Protocol,
58 delegate_transition, initialize,
59};
60pub use user_event::{
61 ChildInputIngress, ComposedEvent, EventIngress, EventLayer, Here, Ingress, InjectEvent, Inside,
62 RecoverEvent, User, UserEvent,
63};
64
65/// Generate the nominal protocol, closed effect products, and exact `Behavior`
66/// wiring for an inherent impl. `addr` and `message` are required. Omitting
67/// `sends`, `births`, or `error` selects the capability-free `NoSends`,
68/// `NoBirths`, or `Never` type respectively.
69///
70/// A `sends = { lane: Product }` declaration generates `ActorSends`, one
71/// distinct `ActorSendsLane` selector per field, and structural `SendEffects`,
72/// `SendsFor`, [`SendSettlements`], and `InterpretSends` implementations. The
73/// doc-hidden `ActorSettlements` product keeps the same semantic field names
74/// and has one runtime-independent type. The macro also generates an
75/// `ActorActions` extension trait with one fluent `send_lane` method per named
76/// lane. Each method delegates to [`AppendSend`], changing only the send leg
77/// while preserving creations and the exact next-behavior verdict. A
78/// `births = { lane: Child }` declaration generates `ActorChildren` as the
79/// exact closed child algebra. One child remains its direct concrete type;
80/// multiple alternatives form `ChildChoice` in declaration order. The macro
81/// also generates one nominal role per declaration and an `ActorChild`
82/// namespace for those roles. Every role implements both [`ChildRole`] for its
83/// authored parent and [`ChildOccurrence`] for sealed resolution against that
84/// parent or a topology-transparent wrapper. Creation remains an authored
85/// [`Creations`] or [`Children`] value and is never performed by the macro.
86///
87/// Invalid receivers are rejected at compile time.
88///
89/// ```compile_fail
90/// use behavior::{Actions, BehaviorActed, MailAddr};
91///
92/// struct Invalid;
93/// #[behavior::behavior(
94/// addr = MailAddr,
95/// message = u8,
96/// )]
97/// impl Invalid {
98/// fn init(&self) -> BehaviorActed<Self> {
99/// Ok(Actions::cont())
100/// }
101/// fn receive(&mut self, _: MailAddr, _: u8) -> BehaviorActed<Self> {
102/// Ok(Actions::cont())
103/// }
104/// }
105/// ```
106///
107/// Missing receive methods are rejected by the macro itself:
108///
109/// ```compile_fail
110/// use behavior::MailAddr;
111/// struct Missing;
112/// #[behavior::behavior(
113/// addr = MailAddr,
114/// message = u8,
115/// )]
116/// impl Missing {
117/// }
118/// ```
119///
120/// Async behavior methods cannot introduce an erased or alternate execution
121/// path:
122///
123/// ```compile_fail
124/// use behavior::{Actions, BehaviorActed, MailAddr};
125/// struct Async;
126/// #[behavior::behavior(
127/// addr = MailAddr,
128/// message = u8,
129/// )]
130/// impl Async {
131/// async fn init(&mut self) -> BehaviorActed<Self> {
132/// Ok(Actions::cont())
133/// }
134/// fn receive(&mut self, _: MailAddr, _: u8) -> BehaviorActed<Self> {
135/// Ok(Actions::cont())
136/// }
137/// }
138/// ```
139///
140/// Undeclared send lanes have no selector and cannot be emitted:
141///
142/// ```compile_fail
143/// use behavior::{Actions, BehaviorActed, MailAddr, SendEffects};
144/// struct Sender;
145/// #[behavior::behavior(addr = MailAddr, message = (), sends = { replies: Vec<u8> })]
146/// impl Sender {
147/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
148/// let mut sends = SenderSends::empty();
149/// sends.send::<_, SenderSendsUndeclared>(1);
150/// Ok(Actions::send(sends))
151/// }
152/// }
153/// ```
154///
155/// Generated lane methods accept only inputs supported by that lane:
156///
157/// ```compile_fail
158/// use behavior::{Actions, BehaviorActed, MailAddr};
159/// struct Sender;
160/// #[behavior::behavior(addr = MailAddr, message = (), sends = { replies: Vec<u8> })]
161/// impl Sender {
162/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
163/// Ok(Actions::cont().send_replies("not a u8"))
164/// }
165/// }
166/// ```
167///
168/// A child absent from the declared closed birth product cannot be created:
169///
170/// ```compile_fail
171/// use behavior::{Actions, BehaviorActed, CreationSequence, Creations, CreateChild, MailAddr};
172/// struct Declared;
173/// #[behavior::behavior(addr = MailAddr, message = behavior::Never)]
174/// impl Declared {
175/// fn receive(&mut self, _: MailAddr, message: behavior::Never) -> BehaviorActed<Self> {
176/// match message {}
177/// }
178/// }
179/// struct Other;
180/// #[behavior::behavior(addr = MailAddr, message = behavior::Never)]
181/// impl Other {
182/// fn receive(&mut self, _: MailAddr, message: behavior::Never) -> BehaviorActed<Self> {
183/// match message {}
184/// }
185/// }
186/// struct Root { creations: CreationSequence }
187/// #[behavior::behavior(addr = MailAddr, message = (), births = { declared: Declared })]
188/// impl Root {
189/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
190/// let id = self.creations.issue().expect("fixture creation ID");
191/// Ok(Actions::create(Creations::one(CreateChild::birth(id, Other))))
192/// }
193/// }
194/// ```
195///
196/// Every generated send lane remains a separate interpreter obligation:
197///
198/// ```compile_fail
199/// use behavior::{BehaviorActed, Delivery, InterpretItem, InterpretSends, ItemSettlement,
200/// MailAddr, MessageProtocol, Never};
201/// struct Root;
202/// type AuditProtocol = MessageProtocol<MailAddr, u8>;
203/// type MetricsProtocol = MessageProtocol<MailAddr, u16>;
204/// #[behavior::behavior(addr = MailAddr, message = (), sends = {
205/// audit: Vec<Delivery<AuditProtocol>>,
206/// metrics: Vec<Delivery<MetricsProtocol>>,
207/// })]
208/// impl Root {
209/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
210/// Ok(behavior::Actions::cont())
211/// }
212/// }
213/// struct Incomplete;
214/// impl<RootEvent, Path> InterpretItem<Delivery<AuditProtocol>, RootEvent, Path> for Incomplete {
215/// fn interpret_item(&mut self, _: Delivery<AuditProtocol>) -> impl core::future::Future<
216/// Output = ItemSettlement<Delivery<AuditProtocol>, (), Never, Never>,
217/// > + Send {
218/// async { ItemSettlement::Accepted(()) }
219/// }
220/// }
221/// fn require_complete()
222/// where
223/// RootSends: InterpretSends<Incomplete, behavior::User<MailAddr, ()>, behavior::Here>,
224/// {}
225/// ```
226///
227/// Generated child products likewise require one [`EstablishChild`]
228/// implementation for every declared alternative. [`DispatchBirth`] owns the
229/// compile-denial example so this crate overview does not duplicate it.
230///
231/// Two declared roles remain distinct even when they use the same behavior:
232///
233/// ```compile_fail
234/// use behavior::{Behavior, BehaviorActed, ChildDelivery, CreationSequence, MailAddr, Never};
235/// struct Worker;
236/// #[behavior::behavior(addr = MailAddr, message = ())]
237/// impl Worker {
238/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
239/// Ok(behavior::Actions::cont())
240/// }
241/// }
242/// struct Root;
243/// #[behavior::behavior(addr = MailAddr, message = Never, births = {
244/// primary: Worker,
245/// backup: Worker,
246/// })]
247/// impl Root {
248/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
249/// match message {}
250/// }
251/// }
252/// fn requires_primary(
253/// _: ChildDelivery<<Worker as Behavior>::Protocol, RootChildrenPrimary>,
254/// ) {}
255/// let mut sequence = CreationSequence::new();
256/// let id = sequence.issue().expect("fixture creation ID");
257/// let backup = ChildDelivery::<<Worker as Behavior>::Protocol, RootChildrenBackup>::after(id, ());
258/// requires_primary(backup);
259/// ```
260///
261/// Named topology selectors accept only the child declared for that parent
262/// role, which lets an application builder remain entirely static:
263///
264/// ```compile_fail
265/// use behavior::{Behavior, BehaviorActed, ChildRole, MailAddr, Never};
266/// struct Worker;
267/// #[behavior::behavior(addr = MailAddr, message = Never)]
268/// impl Worker {
269/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
270/// match message {}
271/// }
272/// }
273/// struct Query;
274/// #[behavior::behavior(addr = MailAddr, message = Never)]
275/// impl Query {
276/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
277/// match message {}
278/// }
279/// }
280/// struct Root;
281/// #[behavior::behavior(addr = MailAddr, message = Never, births = { workers: Worker })]
282/// impl Root {
283/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
284/// match message {}
285/// }
286/// }
287/// fn child<Parent, Role>(_: Role, _: Role::Child)
288/// where
289/// Parent: Behavior,
290/// Role: ChildRole<Parent>,
291/// {}
292/// child::<Root, _>(RootChild::Workers, Query);
293/// ```
294pub use behavior_macros::behavior;