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