Skip to main content

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;