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