behavior_actors/atomic/
diagnostic.rs1use core::convert::Infallible;
4
5use behavior::{
6 ActionItem, EndpointAddress, EstablishedRecipient, ExactDeliveryReason, InterpretationProgress,
7 InterpreterRequest, ItemSettlement, LogicalDeliveryReason, Never, NoReturnToEmitter, Protocol,
8 Recipient, finish_item, prepare_item,
9};
10
11mod sealed {
12 pub trait DiagnosticRoute<Diagnostic> {}
13}
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17pub enum DiagnosticDisposition<Route> {
18 DeliverTo(Route),
20 Terminate,
22}
23
24impl<Route> DiagnosticDisposition<Route> {
25 #[must_use]
27 pub const fn deliver_to(route: Route) -> Self {
28 Self::DeliverTo(route)
29 }
30
31 pub(crate) fn action<Diagnostic>(
32 &self,
33 diagnostic: Diagnostic,
34 ) -> DiagnosticAction<Route, Diagnostic>
35 where
36 Route: Clone,
37 {
38 match self {
39 Self::DeliverTo(route) => DiagnosticAction::deliver(route.clone(), diagnostic),
40 Self::Terminate => DiagnosticAction::terminal(diagnostic),
41 }
42 }
43}
44
45impl DiagnosticDisposition<Infallible> {
46 #[must_use]
48 pub const fn terminate() -> Self {
49 Self::Terminate
50 }
51}
52
53pub trait DiagnosticRoute<Diagnostic>: sealed::DiagnosticRoute<Diagnostic> + Send + Sized {
55 type Rejection: Send;
56 type LogicalProtocols: behavior::BirthProtocolProduct;
57}
58
59impl<P> sealed::DiagnosticRoute<P::Msg> for Recipient<P>
60where
61 P: Protocol,
62 P::Addr: Send,
63 P::Msg: Send,
64{
65}
66
67impl<P> DiagnosticRoute<P::Msg> for Recipient<P>
68where
69 P: Protocol,
70 P::Addr: Send,
71 P::Msg: Send,
72{
73 type Rejection = LogicalDeliveryReason;
74 type LogicalProtocols = behavior::BirthProtocol<P, behavior::NoBirthProtocols>;
75}
76
77impl<P> sealed::DiagnosticRoute<P::Msg> for EstablishedRecipient<P>
78where
79 P: Protocol,
80 P::Addr: EndpointAddress,
81 <P::Addr as EndpointAddress>::Established<P>: Send,
82 P::Msg: Send,
83{
84}
85
86impl<P> DiagnosticRoute<P::Msg> for EstablishedRecipient<P>
87where
88 P: Protocol,
89 P::Addr: EndpointAddress,
90 <P::Addr as EndpointAddress>::Established<P>: Send,
91 P::Msg: Send,
92{
93 type Rejection = ExactDeliveryReason;
94 type LogicalProtocols = behavior::NoBirthProtocols;
95}
96
97impl<Diagnostic> sealed::DiagnosticRoute<Diagnostic> for Infallible where Diagnostic: Send {}
98
99impl<Diagnostic> DiagnosticRoute<Diagnostic> for Infallible
100where
101 Diagnostic: Send,
102{
103 type Rejection = Never;
104 type LogicalProtocols = behavior::NoBirthProtocols;
105}
106
107#[must_use = "a diagnostic action must be interpreted or retained"]
117pub enum DiagnosticAction<Route, Diagnostic> {
118 Deliver {
119 route: Route,
120 diagnostic: Diagnostic,
121 },
122 Terminal {
123 diagnostic: Diagnostic,
124 },
125}
126
127impl<Route, Diagnostic> DiagnosticAction<Route, Diagnostic> {
128 #[must_use]
130 pub const fn deliver(route: Route, diagnostic: Diagnostic) -> Self {
131 Self::Deliver { route, diagnostic }
132 }
133
134 #[must_use]
136 pub const fn terminal(diagnostic: Diagnostic) -> Self {
137 Self::Terminal { diagnostic }
138 }
139}
140
141impl<Route, Diagnostic> InterpreterRequest for DiagnosticAction<Route, Diagnostic>
142where
143 Route: DiagnosticRoute<Diagnostic>,
144{
145 type ReturnToEmitter = NoReturnToEmitter;
146 type LogicalProtocols = Route::LogicalProtocols;
147}
148
149impl<Route, Diagnostic> ActionItem for DiagnosticAction<Route, Diagnostic>
150where
151 Route: DiagnosticRoute<Diagnostic>,
152 Diagnostic: Send,
153{
154 type Custody = (Option<Self>, Option<Self::Reply>);
155 type Input<'a>
156 = &'a mut Option<Self>
157 where
158 Self: 'a;
159 type Reply = ItemSettlement<Self, Self::Accepted, Self::Rejection, Self::Prerequisite>;
160
161 fn prepare_interpretation(
162 progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
163 ) {
164 prepare_item::<Self>(progress);
165 }
166
167 fn interpretation_input<'a>(
168 custody: &'a mut Self::Custody,
169 ) -> Option<(Self::Input<'a>, &'a mut Option<Self::Reply>)>
170 where
171 Self: 'a,
172 {
173 match custody {
174 (input @ Some(_), received @ None) => Some((input, received)),
175 _ => None,
176 }
177 }
178
179 fn finish_interpretation(
180 progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
181 ) {
182 finish_item::<Self>(progress);
183 }
184
185 type Accepted = DiagnosticAccepted<Diagnostic>;
186 type Rejection = Route::Rejection;
187 type Prerequisite = Never;
188
189 fn retain_accepted(accepted: Self::Accepted) -> Option<Self::Accepted> {
190 match accepted {
191 DiagnosticAccepted::Delivered => None,
192 DiagnosticAccepted::Terminal(diagnostic) => {
193 Some(DiagnosticAccepted::Terminal(diagnostic))
194 }
195 }
196 }
197}
198
199#[must_use = "terminal diagnostic custody must be retained"]
201pub enum DiagnosticAccepted<Diagnostic> {
202 Delivered,
203 Terminal(Diagnostic),
204}
205
206impl<Diagnostic> DiagnosticAccepted<Diagnostic> {
207 #[must_use]
209 pub const fn delivered() -> Self {
210 Self::Delivered
211 }
212
213 #[must_use]
215 pub const fn terminal(diagnostic: Diagnostic) -> Self {
216 Self::Terminal(diagnostic)
217 }
218}