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> {
300 inner: E,
301 label: &'static str,
302 log: Rc<RefCell<Vec<&'static str>>>,
303 }
304 impl<E: Executor> Executor for RecordingExecutor<E> {
305 type Error = E::Error;
306 fn execute(&mut self, execution: Execution) -> Result<Outcome, Self::Error> {
307 self.log.borrow_mut().push(self.label);
308 self.inner.execute(execution)
309 }
310 }
311 struct Recorder {
312 label: &'static str,
313 log: Rc<RefCell<Vec<&'static str>>>,
314 }
315 impl<E: Executor> Middleware<E> for Recorder {
316 type Executor = RecordingExecutor<E>;
317 fn wrap(&self, inner: E) -> Self::Executor {
318 RecordingExecutor {
319 inner,
320 label: self.label,
321 log: Rc::clone(&self.log),
322 }
323 }
324 }
325
326 let log: Rc<RefCell<Vec<&'static str>>> = Rc::new(RefCell::new(Vec::new()));
327 let composed = Composition::new()
328 .then(Recorder {
329 label: "first",
330 log: Rc::clone(&log),
331 })
332 .then(Recorder {
333 label: "second",
334 log: Rc::clone(&log),
335 });
336 let mut executor = composed.wrap(DummyExecutor);
337 executor.execute(dummy_execution()).unwrap();
338
339 assert_eq!(*log.borrow(), vec!["first", "second"]);
341 }
342}