1#![forbid(unsafe_code)]
4#![warn(missing_docs)]
5
6use pacta_contract::Pact;
7
8pub use pacta_contract::{Outcome, Settlement};
9
10#[derive(Debug, Clone)]
16#[non_exhaustive]
17pub struct Execution {
18 pub pact: Pact,
20}
21
22impl Execution {
23 #[must_use]
25 pub fn new(pact: Pact) -> Self {
26 Self { pact }
27 }
28}
29
30pub trait Executor {
32 type Error: std::error::Error;
34
35 fn execute(&mut self, execution: Execution) -> Result<Outcome, Self::Error>;
37}
38
39pub trait Middleware<E> {
43 type Executor: Executor;
45
46 fn wrap(&self, executor: E) -> Self::Executor;
48}
49
50#[derive(Debug, Default, Clone, Copy)]
54pub struct Identity;
55
56impl<E: Executor> Middleware<E> for Identity {
57 type Executor = E;
58
59 fn wrap(&self, executor: E) -> Self::Executor {
60 executor
61 }
62}
63
64#[derive(Debug, Default, Clone, Copy)]
69pub struct Stack<Inner, Outer> {
70 inner: Inner,
71 outer: Outer,
72}
73
74impl<Inner, Outer> Stack<Inner, Outer> {
75 #[must_use]
78 pub const fn new(inner: Inner, outer: Outer) -> Self {
79 Self { inner, outer }
80 }
81}
82
83impl<E, Inner, Outer> Middleware<E> for Stack<Inner, Outer>
84where
85 E: Executor,
86 Inner: Middleware<E>,
87 Outer: Middleware<Inner::Executor>,
88{
89 type Executor = Outer::Executor;
90
91 fn wrap(&self, executor: E) -> Self::Executor {
92 self.outer.wrap(self.inner.wrap(executor))
93 }
94}
95
96#[derive(Debug, Default, Clone, Copy)]
111pub struct Composition<M> {
112 middleware: M,
113}
114
115impl Composition<Identity> {
116 #[must_use]
118 pub const fn new() -> Self {
119 Self {
120 middleware: Identity,
121 }
122 }
123}
124
125impl<M> Composition<M> {
126 #[must_use]
130 pub fn then<N>(self, next: N) -> Composition<Stack<N, M>> {
131 Composition {
132 middleware: Stack::new(next, self.middleware),
133 }
134 }
135}
136
137impl<E, M> Middleware<E> for Composition<M>
138where
139 E: Executor,
140 M: Middleware<E>,
141{
142 type Executor = M::Executor;
143
144 fn wrap(&self, executor: E) -> Self::Executor {
145 self.middleware.wrap(executor)
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[derive(Debug)]
154 struct DummyError;
155
156 impl std::fmt::Display for DummyError {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 write!(f, "dummy error")
159 }
160 }
161
162 impl std::error::Error for DummyError {}
163
164 struct DummyExecutor;
165 impl Executor for DummyExecutor {
166 type Error = DummyError;
167 fn execute(&mut self, _execution: Execution) -> Result<Outcome, Self::Error> {
168 Ok(Outcome::Fulfilled)
169 }
170 }
171
172 struct IdentityExecutor<E> {
173 inner: E,
174 }
175 impl<E: Executor> Executor for IdentityExecutor<E> {
176 type Error = E::Error;
177 fn execute(&mut self, execution: Execution) -> Result<Outcome, Self::Error> {
178 self.inner.execute(execution)
179 }
180 }
181
182 struct IdentityMiddleware;
183 impl<E: Executor> Middleware<E> for IdentityMiddleware {
184 type Executor = IdentityExecutor<E>;
185 fn wrap(&self, executor: E) -> Self::Executor {
186 IdentityExecutor { inner: executor }
187 }
188 }
189
190 struct BreachExecutor<E> {
191 _inner: E,
192 }
193 impl<E: Executor> Executor for BreachExecutor<E> {
194 type Error = E::Error;
195 fn execute(&mut self, _execution: Execution) -> Result<Outcome, Self::Error> {
196 Ok(Outcome::Breached)
197 }
198 }
199
200 struct BreachMiddleware;
201 impl<E: Executor> Middleware<E> for BreachMiddleware {
202 type Executor = BreachExecutor<E>;
203 fn wrap(&self, executor: E) -> Self::Executor {
204 BreachExecutor { _inner: executor }
205 }
206 }
207
208 fn dummy_execution() -> Execution {
209 Execution::new(Pact::new(
210 Default::default(),
211 "dummy_docket".to_string(),
212 "dummy_kind".to_string(),
213 vec![],
214 ))
215 }
216
217 #[test]
218 fn identity_middleware_preserves_fulfilled() {
219 let middleware = IdentityMiddleware;
220 let mut executor = middleware.wrap(DummyExecutor);
221 let outcome = executor.execute(dummy_execution()).unwrap();
222 assert_eq!(outcome, Outcome::Fulfilled);
223 }
224
225 #[test]
226 fn breach_middleware_alters_outcome() {
227 let middleware = BreachMiddleware;
228 let mut executor = middleware.wrap(DummyExecutor);
229 let outcome = executor.execute(dummy_execution()).unwrap();
230 assert_eq!(outcome, Outcome::Breached);
231 }
232
233 #[test]
234 fn stacked_middleware_composes() {
235 let inner = IdentityMiddleware.wrap(DummyExecutor);
240 let mut stacked = IdentityMiddleware.wrap(inner);
241 let outcome = stacked.execute(dummy_execution()).unwrap();
242 assert_eq!(outcome, Outcome::Fulfilled);
243 }
244
245 #[test]
246 fn stacked_middleware_preserves_ordering() {
247 let inner = IdentityMiddleware.wrap(DummyExecutor);
250 let mut stacked = BreachMiddleware.wrap(inner);
251 let outcome = stacked.execute(dummy_execution()).unwrap();
252 assert_eq!(outcome, Outcome::Breached);
253 }
254
255 #[test]
256 fn identity_wrap_returns_the_executor_unchanged() {
257 let mut executor = Identity.wrap(DummyExecutor);
259 assert_eq!(
260 executor.execute(dummy_execution()).unwrap(),
261 Outcome::Fulfilled
262 );
263 }
264
265 #[test]
266 fn stack_is_itself_a_middleware() {
267 let stack = Stack::new(IdentityMiddleware, BreachMiddleware);
270 let mut executor = stack.wrap(DummyExecutor);
271 assert_eq!(
273 executor.execute(dummy_execution()).unwrap(),
274 Outcome::Breached
275 );
276 }
277
278 #[test]
279 fn composition_assembles_and_drives_to_a_settlement() {
280 let composed = Composition::new()
283 .then(IdentityMiddleware)
284 .then(IdentityMiddleware);
285 let mut executor = composed.wrap(DummyExecutor);
286 assert_eq!(
287 executor.execute(dummy_execution()).unwrap(),
288 Outcome::Fulfilled
289 );
290 }
291
292 #[test]
293 fn composition_orders_first_added_outermost() {
294 use std::cell::RefCell;
295 use std::rc::Rc;
296
297 struct RecordingExecutor<E> {
302 inner: E,
303 label: &'static str,
304 log: Rc<RefCell<Vec<String>>>,
305 }
306 impl<E: Executor> Executor for RecordingExecutor<E> {
307 type Error = E::Error;
308 fn execute(&mut self, execution: Execution) -> Result<Outcome, Self::Error> {
309 self.log.borrow_mut().push(format!("{}:enter", self.label));
310 let outcome = self.inner.execute(execution);
311 self.log.borrow_mut().push(format!("{}:exit", self.label));
312 outcome
313 }
314 }
315 struct Recorder {
316 label: &'static str,
317 log: Rc<RefCell<Vec<String>>>,
318 }
319 impl<E: Executor> Middleware<E> for Recorder {
320 type Executor = RecordingExecutor<E>;
321 fn wrap(&self, inner: E) -> Self::Executor {
322 RecordingExecutor {
323 inner,
324 label: self.label,
325 log: Rc::clone(&self.log),
326 }
327 }
328 }
329
330 struct RecordingInner {
332 log: Rc<RefCell<Vec<String>>>,
333 }
334 impl Executor for RecordingInner {
335 type Error = DummyError;
336 fn execute(&mut self, _execution: Execution) -> Result<Outcome, Self::Error> {
337 self.log.borrow_mut().push("executor".to_string());
338 Ok(Outcome::Fulfilled)
339 }
340 }
341
342 let log: Rc<RefCell<Vec<String>>> = Rc::new(RefCell::new(Vec::new()));
343 let composed = Composition::new()
344 .then(Recorder {
345 label: "first",
346 log: Rc::clone(&log),
347 })
348 .then(Recorder {
349 label: "second",
350 log: Rc::clone(&log),
351 });
352 let mut executor = composed.wrap(RecordingInner {
353 log: Rc::clone(&log),
354 });
355 executor.execute(dummy_execution()).unwrap();
356
357 assert_eq!(
360 *log.borrow(),
361 vec![
362 "first:enter",
363 "second:enter",
364 "executor",
365 "second:exit",
366 "first:exit",
367 ]
368 );
369 }
370}