Skip to main content

behavior_actors/
requirements.rs

1//! Static logical-delivery projections for handwritten actor send products.
2
3use behavior::{
4    BirthProtocol, EndpointAddress, LogicalDeliveryProtocols, NoBirthProtocols, Protocol,
5};
6
7impl<P> LogicalDeliveryProtocols
8    for crate::ReplyDeliveries<behavior::Delivery<P>, behavior::EstablishedDelivery<P>>
9where
10    P: Protocol,
11    P::Addr: EndpointAddress,
12{
13    type Protocols = BirthProtocol<P, NoBirthProtocols>;
14}
15
16impl<T> LogicalDeliveryProtocols for crate::HeterogeneousShutdownSends<T> {
17    type Protocols = NoBirthProtocols;
18}
19
20#[cfg(test)]
21mod tests {
22    use super::*;
23    use behavior::{
24        Actions, Behavior, BehaviorActed, Births, ChildChoice, MailAddr, Never, NoBirths, Protocol,
25        User,
26    };
27
28    struct RootProtocol;
29    struct SharedProtocol;
30    struct LeafProtocol;
31    struct ExternalProtocol;
32    macro_rules! protocol {
33        ($protocol:ty) => {
34            impl Protocol for $protocol {
35                type Addr = MailAddr;
36                type Msg = ();
37            }
38        };
39    }
40
41    protocol!(RootProtocol);
42    protocol!(SharedProtocol);
43    protocol!(LeafProtocol);
44    protocol!(ExternalProtocol);
45
46    struct Leaf;
47    struct Primary;
48    struct Fallback;
49    struct Root;
50
51    macro_rules! behavior {
52        ($behavior:ty, $protocol:ty, $birth:ty, $sends:ty) => {
53            impl Behavior for $behavior {
54                type Protocol = $protocol;
55                type Event = User<MailAddr, ()>;
56                type Sends = $sends;
57                type Ph = Never;
58                type Error = Never;
59                type Birth = $birth;
60
61                fn transition(
62                    &mut self,
63                    _: behavior::ActiveTurn,
64                    _: Self::Event,
65                ) -> BehaviorActed<Self> {
66                    Ok(Actions::cont())
67                }
68            }
69        };
70    }
71
72    behavior!(Leaf, LeafProtocol, NoBirths, Vec<Never>);
73    behavior!(Primary, SharedProtocol, Births<Leaf>, Vec<Never>);
74    behavior!(Fallback, SharedProtocol, NoBirths, Vec<Never>);
75    behavior!(
76        Root,
77        RootProtocol,
78        Births<ChildChoice<Primary, ChildChoice<Fallback, Never>>>,
79        Vec<behavior::Delivery<ExternalProtocol>>
80    );
81    #[test]
82    fn transitive_births_preserve_every_protocol_occurrence_and_exclude_sends() {
83        type Requirements = <Root as behavior::BirthProtocols>::Protocols;
84
85        fn contains<P: Protocol, Position, Product: behavior::BirthProtocolAt<P, Position>>() {}
86
87        contains::<RootProtocol, behavior::BirthProtocolHead, Requirements>();
88        contains::<
89            SharedProtocol,
90            behavior::BirthProtocolTail<behavior::BirthProtocolHead>,
91            Requirements,
92        >();
93        contains::<
94            LeafProtocol,
95            behavior::BirthProtocolTail<behavior::BirthProtocolTail<behavior::BirthProtocolHead>>,
96            Requirements,
97        >();
98        contains::<
99            SharedProtocol,
100            behavior::BirthProtocolTail<
101                behavior::BirthProtocolTail<
102                    behavior::BirthProtocolTail<behavior::BirthProtocolHead>,
103                >,
104            >,
105            Requirements,
106        >();
107    }
108
109    #[test]
110    fn transparent_wrapper_preserves_inner_transitive_requirements_once() {
111        type Wrapped = crate::StopOnShutdown<Primary>;
112        type Requirements = <Wrapped as behavior::BirthProtocols>::Protocols;
113        type Expected =
114            BirthProtocol<SharedProtocol, BirthProtocol<LeafProtocol, NoBirthProtocols>>;
115
116        trait Same<T> {}
117        impl<T> Same<T> for T {}
118        fn exact<T: Same<Expected>>() {}
119        exact::<Requirements>();
120    }
121
122    #[test]
123    fn independently_projected_products_compose_without_losing_occurrences() {
124        type LeafRequirements = <Leaf as behavior::BirthProtocols>::Protocols;
125        type FallbackRequirements = <Fallback as behavior::BirthProtocols>::Protocols;
126        type Combined =
127            <LeafRequirements as behavior::BirthProtocolProduct>::Append<FallbackRequirements>;
128        type Expected =
129            BirthProtocol<LeafProtocol, BirthProtocol<SharedProtocol, NoBirthProtocols>>;
130
131        trait Same<T> {}
132        impl<T> Same<T> for T {}
133        fn exact<T: Same<Expected>>() {}
134        exact::<Combined>();
135    }
136
137    #[test]
138    fn logical_projection_follows_named_lanes_and_excludes_nonlogical_lanes() {
139        type Named = crate::DeliveryOutcomes<
140            Vec<behavior::Delivery<ExternalProtocol>>,
141            Vec<behavior::Delivery<SharedProtocol>>,
142        >;
143        type NamedActual = <Named as LogicalDeliveryProtocols>::Protocols;
144        type NamedExpected =
145            BirthProtocol<ExternalProtocol, BirthProtocol<SharedProtocol, NoBirthProtocols>>;
146        trait Same<T> {}
147        impl<T> Same<T> for T {}
148        fn exact<T: Same<Expected>, Expected>() {}
149
150        exact::<NamedActual, NamedExpected>();
151    }
152
153    #[test]
154    fn lease_and_presence_products_keep_both_wrapper_orders() {
155        type Lease = crate::LeaseSends<
156            Vec<behavior::Delivery<SharedProtocol>>,
157            behavior::InterpreterRequests<crate::ScheduleAfter>,
158        >;
159        type Presence = crate::PresenceSends<
160            Vec<behavior::Delivery<ExternalProtocol>>,
161            behavior::InterpreterRequests<crate::ScheduleAfter>,
162        >;
163        type PresenceFirst =
164            <behavior::SendLayer<Lease, Presence> as LogicalDeliveryProtocols>::Protocols;
165        type LeaseFirst =
166            <behavior::SendLayer<Presence, Lease> as LogicalDeliveryProtocols>::Protocols;
167        type PresenceFirstExpected =
168            BirthProtocol<ExternalProtocol, BirthProtocol<SharedProtocol, NoBirthProtocols>>;
169        type LeaseFirstExpected =
170            BirthProtocol<SharedProtocol, BirthProtocol<ExternalProtocol, NoBirthProtocols>>;
171
172        trait Same<T> {}
173        impl<T> Same<T> for T {}
174        fn exact<T: Same<Expected>, Expected>() {}
175
176        exact::<PresenceFirst, PresenceFirstExpected>();
177        exact::<LeaseFirst, LeaseFirstExpected>();
178    }
179
180    #[test]
181    fn wrapper_projection_preserves_root_and_transitive_logical_occurrences() {
182        type Wrapped = crate::StopOnShutdown<Root>;
183        type Actual = <Wrapped as behavior::LogicalHostRequirements>::LogicalHosts;
184        type Expected = BirthProtocol<ExternalProtocol, NoBirthProtocols>;
185
186        trait Same<T> {}
187        impl<T> Same<T> for T {}
188        fn exact<T: Same<Expected>>() {}
189
190        exact::<Actual>();
191    }
192}