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//! 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, CreateChild,
42 CreationCorrelation, CreationId, CreationKind, CreationRejection, CreationSequence, Creations,
43 DeclaredChildOccurrence, Delivery, DispatchBirth, EndpointAddress, EstablishChild,
44 EstablishedActor, EstablishedCreation, EstablishedDelivery, EstablishedRecipient,
45 ExactDeliveryReason, InterpretEstablished, LogicalDeliveryReason, MailAddr, NoBirthProtocols,
46 NoBirths, NoChildren, Recipient, ResolveChildOccurrence, ResolvedChild, ResolvedChildPosition,
47 RetirementBirths, RoleChild, RoleProtocol, RoutedCreation, StructuralChildOccurrence,
48};
49pub use effects::{
50 Acted, ActionItem, ActionItemResult, ActionSettlement, ActionSettlements, Actions, AppendSend,
51 Become, BehaviorSettlements, ClassifySettlement, CreationEvent, CreationSettlement,
52 CreationSettlements, CreationsSettled, InterpretCreations, InterpretItem, InterpretSends,
53 Interpretation, InterpreterFault, InterpreterRequest, InterpreterRequests, ItemSettlement,
54 LogicalDeliveryProtocols, NoReturnToEmitter, NoSends, Own, ParentReportReason, ReportToParent,
55 RetirementCreationSettlement, ReturnsToEmitter, SendEffects, SendInput, SendLayer,
56 SendSettlements, SendsFor, SettledItem, SettlementStatus, SourceAction, SourceActions,
57 SourceAdmission, SourceCustody, SourceSettlementCustody, SourceSettlements, settle_in_order,
58 settle_item,
59};
60pub use next::{Never, Step, Stopped};
61pub use transition::{
62 ActiveTurn, Behavior, BehaviorActed, BehaviorAddr, BehaviorBase, BehaviorLayer,
63 BehaviorMessage, InitializationTurn, LogicalHostRequirements, MessageProtocol, Protocol,
64 delegate_transition, initialize,
65};
66pub use user_event::{
67 ChildInputIngress, ComposedEvent, EventIngress, EventLayer, Here, Ingress, InjectEvent, Inside,
68 RecoverEvent, User, UserEvent,
69};
70
71/// Generate the nominal protocol, closed effect products, and exact `Behavior`
72/// wiring for an inherent impl. `addr` and `message` are required. Omitting
73/// `sends`, `births`, or `error` selects the capability-free `NoSends`,
74/// `NoBirths`, or `Never` type respectively.
75///
76/// A `sends = { lane: Product }` declaration generates `ActorSends`, one
77/// distinct `ActorSendsLane` selector per field, and structural `SendEffects`,
78/// `SendsFor`, [`SendSettlements`], and `InterpretSends` implementations. The
79/// doc-hidden `ActorSettlements` product keeps the same semantic field names
80/// and has one runtime-independent type. The macro also generates an
81/// `ActorActions` extension trait with one fluent `send_lane` method per named
82/// lane. Each method delegates to [`AppendSend`], changing only the send leg
83/// while preserving creations and the exact next-behavior verdict. A
84/// `births = { lane: Child }` declaration generates `ActorChildren` as the
85/// exact closed child algebra. One child remains its direct concrete type;
86/// multiple alternatives form `ChildChoice` in declaration order. The macro
87/// also generates one nominal role per declaration and an `ActorChild`
88/// namespace for those roles. Every role implements both [`ChildRole`] for its
89/// authored parent and [`ChildOccurrence`] for sealed resolution against that
90/// parent or a topology-transparent wrapper. Creation remains an authored
91/// [`Creations`] or [`Children`] value and is never performed by the macro.
92///
93/// Invalid receivers are rejected at compile time.
94/// A birth-owning generated actor must also select the exact creation-settlement
95/// disposition; there is no implicit discard or generated no-op receiver.
96///
97/// ```compile_fail
98/// struct Child;
99/// #[behavior::behavior(addr = behavior::MailAddr, message = behavior::Never)]
100/// impl Child {
101/// fn receive(
102/// &mut self,
103/// _: behavior::MailAddr,
104/// message: behavior::Never,
105/// ) -> behavior::BehaviorActed<Self> {
106/// match message {}
107/// }
108/// }
109/// struct MissingCreationSettlementDisposition;
110/// #[behavior::behavior(
111/// addr = behavior::MailAddr,
112/// message = behavior::Never,
113/// births = { child: Child },
114/// )]
115/// impl MissingCreationSettlementDisposition {
116/// fn receive(
117/// &mut self,
118/// _: behavior::MailAddr,
119/// message: behavior::Never,
120/// ) -> behavior::BehaviorActed<Self> {
121/// match message {}
122/// }
123/// }
124/// ```
125///
126/// ```compile_fail
127/// use behavior::{Actions, BehaviorActed, MailAddr};
128///
129/// struct Invalid;
130/// #[behavior::behavior(
131/// addr = MailAddr,
132/// message = u8,
133/// )]
134/// impl Invalid {
135/// fn init(&self) -> BehaviorActed<Self> {
136/// Ok(Actions::cont())
137/// }
138/// fn receive(&mut self, _: MailAddr, _: u8) -> BehaviorActed<Self> {
139/// Ok(Actions::cont())
140/// }
141/// }
142/// ```
143///
144/// Missing receive methods are rejected by the macro itself:
145///
146/// ```compile_fail
147/// use behavior::MailAddr;
148/// struct Missing;
149/// #[behavior::behavior(
150/// addr = MailAddr,
151/// message = u8,
152/// )]
153/// impl Missing {
154/// }
155/// ```
156///
157/// Async behavior methods cannot introduce an erased or alternate execution
158/// path:
159///
160/// ```compile_fail
161/// use behavior::{Actions, BehaviorActed, MailAddr};
162/// struct Async;
163/// #[behavior::behavior(
164/// addr = MailAddr,
165/// message = u8,
166/// )]
167/// impl Async {
168/// async fn init(&mut self) -> BehaviorActed<Self> {
169/// Ok(Actions::cont())
170/// }
171/// fn receive(&mut self, _: MailAddr, _: u8) -> BehaviorActed<Self> {
172/// Ok(Actions::cont())
173/// }
174/// }
175/// ```
176///
177/// Undeclared send lanes have no selector and cannot be emitted:
178///
179/// ```compile_fail
180/// use behavior::{Actions, BehaviorActed, MailAddr, SendEffects};
181/// struct Sender;
182/// #[behavior::behavior(addr = MailAddr, message = (), sends = { replies: Vec<u8> })]
183/// impl Sender {
184/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
185/// let mut sends = SenderSends::empty();
186/// sends.send::<_, SenderSendsUndeclared>(1);
187/// Ok(Actions::send(sends))
188/// }
189/// }
190/// ```
191///
192/// Generated lane methods accept only inputs supported by that lane:
193///
194/// ```compile_fail
195/// use behavior::{Actions, BehaviorActed, MailAddr};
196/// struct Sender;
197/// #[behavior::behavior(addr = MailAddr, message = (), sends = { replies: Vec<u8> })]
198/// impl Sender {
199/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
200/// Ok(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/// use behavior::{Actions, BehaviorActed, CreationSequence, Creations, CreateChild, MailAddr};
209/// struct Declared;
210/// #[behavior::behavior(addr = MailAddr, message = behavior::Never)]
211/// impl Declared {
212/// fn receive(&mut self, _: MailAddr, message: behavior::Never) -> BehaviorActed<Self> {
213/// match message {}
214/// }
215/// }
216/// struct Other;
217/// #[behavior::behavior(addr = MailAddr, message = behavior::Never)]
218/// impl Other {
219/// fn receive(&mut self, _: MailAddr, message: behavior::Never) -> BehaviorActed<Self> {
220/// match message {}
221/// }
222/// }
223/// struct Root { creations: CreationSequence }
224/// #[behavior::behavior(
225/// addr = MailAddr,
226/// message = (),
227/// births = { declared: Declared },
228/// creation_settlements = retain_for_retirement,
229/// )]
230/// impl Root {
231/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
232/// let id = self.creations.issue().expect("fixture creation ID");
233/// Ok(Actions::create(Creations::one(CreateChild::birth(id, Other))))
234/// }
235/// }
236/// ```
237///
238/// Every generated send lane remains a separate interpreter obligation:
239///
240/// ```compile_fail
241/// use behavior::{BehaviorActed, Delivery, InterpretItem, InterpretSends, ItemSettlement,
242/// MailAddr, MessageProtocol, Never};
243/// struct Root;
244/// type AuditProtocol = MessageProtocol<MailAddr, u8>;
245/// type MetricsProtocol = MessageProtocol<MailAddr, u16>;
246/// #[behavior::behavior(addr = MailAddr, message = (), sends = {
247/// audit: Vec<Delivery<AuditProtocol>>,
248/// metrics: Vec<Delivery<MetricsProtocol>>,
249/// })]
250/// impl Root {
251/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
252/// Ok(behavior::Actions::cont())
253/// }
254/// }
255/// struct Incomplete;
256/// impl<RootEvent, Path> InterpretItem<Delivery<AuditProtocol>, RootEvent, Path> for Incomplete {
257/// fn interpret_item(&mut self, _: Delivery<AuditProtocol>) -> impl core::future::Future<
258/// Output = ItemSettlement<Delivery<AuditProtocol>, (), Never, Never>,
259/// > + Send {
260/// async { ItemSettlement::Accepted(()) }
261/// }
262/// }
263/// fn require_complete()
264/// where
265/// RootSends: InterpretSends<Incomplete, behavior::User<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/// use behavior::{Behavior, BehaviorActed, ChildDelivery, CreationSequence, MailAddr, Never};
277/// struct Worker;
278/// #[behavior::behavior(addr = MailAddr, message = ())]
279/// impl Worker {
280/// fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
281/// Ok(behavior::Actions::cont())
282/// }
283/// }
284/// struct Root;
285/// #[behavior::behavior(addr = MailAddr, message = Never, births = {
286/// primary: Worker,
287/// backup: Worker,
288/// }, creation_settlements = retain_for_retirement)]
289/// impl Root {
290/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
291/// match message {}
292/// }
293/// }
294/// fn requires_primary(
295/// _: ChildDelivery<<Worker as Behavior>::Protocol, RootChildrenPrimary>,
296/// ) {}
297/// let mut sequence = CreationSequence::new();
298/// let id = sequence.issue().expect("fixture creation ID");
299/// let backup = ChildDelivery::<<Worker as Behavior>::Protocol, RootChildrenBackup>::after(id, ());
300/// requires_primary(backup);
301/// ```
302///
303/// Named topology selectors accept only the child declared for that parent
304/// role, which lets an application builder remain entirely static:
305///
306/// ```compile_fail
307/// use behavior::{Behavior, BehaviorActed, ChildRole, MailAddr, Never};
308/// struct Worker;
309/// #[behavior::behavior(addr = MailAddr, message = Never)]
310/// impl Worker {
311/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
312/// match message {}
313/// }
314/// }
315/// struct Query;
316/// #[behavior::behavior(addr = MailAddr, message = Never)]
317/// impl Query {
318/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
319/// match message {}
320/// }
321/// }
322/// struct Root;
323/// #[behavior::behavior(
324/// addr = MailAddr,
325/// message = Never,
326/// births = { workers: Worker },
327/// creation_settlements = retain_for_retirement,
328/// )]
329/// impl Root {
330/// fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> {
331/// match message {}
332/// }
333/// }
334/// fn child<Parent, Role>(_: Role, _: Role::Child)
335/// where
336/// Parent: Behavior,
337/// Role: ChildRole<Parent>,
338/// {}
339/// child::<Root, _>(RootChild::Workers, Query);
340/// ```
341pub use behavior_macros::behavior;