1use crate::iltp::IltpItem;
2use crate::logic::InterlaceModule;
3
4use super::{
5 CarrierRole, ConnectedCarrier, ConnectedConfig, CoreError, DirectConfig, DirectPair,
6 FixedPointWakeBoundary, InterlaceSide, MachineError, MachinePoll, PeerInput,
7 PeerInputDisposition, ProtocolPhaseToken, StoreCall, StorePosition, StorePositionAdvance,
8};
9
10#[derive(Debug)]
12pub struct InterlaceMachine {
13 owner: InterlaceOwner,
14}
15
16#[derive(Debug)]
17enum InterlaceOwner {
18 Direct(Box<DirectPair>),
19 Connected(Box<ConnectedCarrier>),
20}
21
22impl InterlaceMachine {
23 pub fn new_direct(config: DirectConfig) -> Result<Self, CoreError> {
24 Ok(Self {
25 owner: InterlaceOwner::Direct(Box::new(DirectPair::new(config)?)),
26 })
27 }
28
29 pub fn new_connected(role: CarrierRole, config: ConnectedConfig) -> Result<Self, CoreError> {
30 Ok(Self {
31 owner: InterlaceOwner::Connected(Box::new(ConnectedCarrier::new(role, config)?)),
32 })
33 }
34
35 pub fn protocol_phase_token(&self, side: InterlaceSide) -> Option<ProtocolPhaseToken> {
36 match &self.owner {
37 InterlaceOwner::Direct(pair) => Some(pair.protocol_phase_token(side)),
38 InterlaceOwner::Connected(carrier) => {
39 (carrier.local_protocol_side() == side).then(|| carrier.protocol_phase_token())
40 }
41 }
42 }
43
44 pub fn active_store_call(&self, side: InterlaceSide) -> Option<&StoreCall> {
45 match &self.owner {
46 InterlaceOwner::Direct(pair) => pair.active_store_call(side),
47 InterlaceOwner::Connected(carrier) => carrier
48 .active_store_call()
49 .filter(|call| call.side() == side),
50 }
51 }
52
53 pub fn active_store_call_mut(&mut self, side: InterlaceSide) -> Option<&mut StoreCall> {
54 match &mut self.owner {
55 InterlaceOwner::Direct(pair) => pair.active_store_call_mut(side),
56 InterlaceOwner::Connected(carrier) => carrier
57 .active_store_call_mut()
58 .filter(|call| call.side() == side),
59 }
60 }
61
62 pub fn replace_direct_policy(
63 &mut self,
64 operands: [InterlaceModule; 2],
65 ) -> Result<(), CoreError> {
66 match &mut self.owner {
67 InterlaceOwner::Direct(pair) => pair.replace_policy(operands),
68 InterlaceOwner::Connected(_) => Err(CoreError::InvalidConfig(
69 "connected interlace requires one local replacement operand",
70 )),
71 }
72 }
73
74 pub fn replace_connected_policy(&mut self, operand: InterlaceModule) -> Result<(), CoreError> {
75 match &mut self.owner {
76 InterlaceOwner::Connected(carrier) => carrier.replace_policy(operand),
77 InterlaceOwner::Direct(_) => Err(CoreError::InvalidConfig(
78 "direct interlace requires both replacement operands",
79 )),
80 }
81 }
82
83 pub fn submit_store_call(&mut self, id: u64) -> Result<(), MachineError> {
84 match &mut self.owner {
85 InterlaceOwner::Direct(pair) => pair.submit_store_call(id),
86 InterlaceOwner::Connected(carrier) => carrier.submit_store_call(id),
87 }
88 }
89
90 pub fn try_store_position_advanced(
91 &mut self,
92 boundary: &FixedPointWakeBoundary,
93 position: StorePosition,
94 ) -> StorePositionAdvance {
95 match &mut self.owner {
96 InterlaceOwner::Direct(pair) => pair.try_store_position_advanced(boundary, position),
97 InterlaceOwner::Connected(carrier) => {
98 carrier.try_store_position_advanced(boundary, position)
99 }
100 }
101 }
102
103 pub fn timeout(&mut self, side: InterlaceSide) -> Result<(), CoreError> {
104 match &mut self.owner {
105 InterlaceOwner::Direct(pair) => pair.timeout(side),
106 InterlaceOwner::Connected(carrier) if carrier.local_protocol_side() == side => {
107 carrier.timeout()
108 }
109 InterlaceOwner::Connected(_) => {
110 return Err(CoreError::InvalidConfig(
111 "connected interlace has no endpoint on that side",
112 ));
113 }
114 }
115 Ok(())
116 }
117
118 pub fn can_read_peer_input(&self) -> Result<bool, CoreError> {
119 match &self.owner {
120 InterlaceOwner::Connected(carrier) => Ok(carrier.can_read_peer_input()),
121 InterlaceOwner::Direct(_) => Err(CoreError::InvalidConfig(
122 "direct interlace has no peer stream",
123 )),
124 }
125 }
126
127 pub fn peer_record_ingress(&self) -> Result<super::RecordIngress, CoreError> {
128 match &self.owner {
129 InterlaceOwner::Connected(carrier) => Ok(carrier.peer_record_ingress()),
130 InterlaceOwner::Direct(_) => Err(CoreError::InvalidConfig(
131 "direct interlace has no peer stream",
132 )),
133 }
134 }
135
136 pub fn peer_input_disposition(
137 &self,
138 input: &PeerInput,
139 ) -> Result<PeerInputDisposition, CoreError> {
140 match &self.owner {
141 InterlaceOwner::Connected(carrier) => Ok(carrier.peer_input_disposition(input)),
142 InterlaceOwner::Direct(_) => Err(CoreError::InvalidConfig(
143 "direct interlace has no peer stream",
144 )),
145 }
146 }
147
148 pub fn push_peer_input(&mut self, input: impl Into<PeerInput>) -> Result<(), MachineError> {
149 match &mut self.owner {
150 InterlaceOwner::Connected(carrier) => carrier.push_input(input),
151 InterlaceOwner::Direct(_) => Err(super::machine::integration_machine_error(
152 "direct interlace does not accept peer input",
153 )),
154 }
155 }
156
157 pub fn accept_peer_output(&mut self) -> Result<Vec<IltpItem>, MachineError> {
161 match &mut self.owner {
162 InterlaceOwner::Connected(carrier) => carrier.accept_peer_output(),
163 InterlaceOwner::Direct(_) => Err(super::machine::integration_machine_error(
164 "direct interlace has no peer output",
165 )),
166 }
167 }
168
169 pub fn adopt_operand_cache(&mut self, cache: super::OperandCache) -> Result<(), MachineError> {
174 match &mut self.owner {
175 InterlaceOwner::Connected(carrier) => carrier.adopt_operand_cache(cache),
176 InterlaceOwner::Direct(_) => Err(super::machine::integration_machine_error(
177 "direct interlace has no port",
178 )),
179 }
180 }
181
182 pub fn select_operand(
183 &mut self,
184 selection: Option<super::SessionOperand>,
185 ) -> Result<(), MachineError> {
186 match &mut self.owner {
187 InterlaceOwner::Connected(carrier) => carrier.select_operand(selection),
188 InterlaceOwner::Direct(_) => Err(super::machine::integration_machine_error(
189 "direct interlace has no port",
190 )),
191 }
192 }
193
194 pub fn peer_port(&self) -> Option<&crate::iltp::PortText> {
196 match &self.owner {
197 InterlaceOwner::Connected(carrier) => carrier.peer_port(),
198 InterlaceOwner::Direct(_) => None,
199 }
200 }
201
202 pub fn peer_by(&self) -> Option<&crate::records::ByValue> {
205 match &self.owner {
206 InterlaceOwner::Connected(carrier) => carrier.peer_by(),
207 InterlaceOwner::Direct(_) => None,
208 }
209 }
210
211 pub fn outgoing_encoding(&self) -> Option<crate::iltp::StreamEncoding> {
214 match &self.owner {
215 InterlaceOwner::Connected(carrier) => carrier.outgoing_encoding(),
216 InterlaceOwner::Direct(_) => None,
217 }
218 }
219
220 pub fn incoming_encoding(&self) -> Option<crate::iltp::StreamEncoding> {
223 match &self.owner {
224 InterlaceOwner::Connected(carrier) => carrier.incoming_encoding(),
225 InterlaceOwner::Direct(_) => None,
226 }
227 }
228
229 pub fn peer_diagnostics(&self) -> crate::runtime_values::PeerDiagnostics {
231 crate::runtime_values::PeerDiagnostics {
232 peer_by: self.peer_by().copied(),
233 outgoing_encoding: self.outgoing_encoding(),
234 incoming_encoding: self.incoming_encoding(),
235 }
236 }
237
238 pub fn peer_eof(&mut self) -> Result<(), MachineError> {
239 match &mut self.owner {
240 InterlaceOwner::Connected(carrier) => carrier.peer_eof(),
241 InterlaceOwner::Direct(_) => Err(super::machine::integration_machine_error(
242 "direct interlace has no peer stream",
243 )),
244 }
245 }
246
247 pub fn cancel(&mut self) {
248 match &mut self.owner {
249 InterlaceOwner::Connected(carrier) => carrier.cancel(),
250 InterlaceOwner::Direct(pair) => pair.cancel(),
251 }
252 }
253
254 pub fn poll(&mut self) -> MachinePoll<'_> {
255 match &mut self.owner {
256 InterlaceOwner::Direct(pair) => pair.poll(),
257 InterlaceOwner::Connected(carrier) => carrier.poll(),
258 }
259 }
260}