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#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[derive(Debug)]
55 struct DummyError;
56
57 impl std::fmt::Display for DummyError {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 write!(f, "dummy error")
60 }
61 }
62
63 impl std::error::Error for DummyError {}
64
65 struct DummyExecutor;
66 impl Executor for DummyExecutor {
67 type Error = DummyError;
68 fn execute(&mut self, _execution: Execution) -> Result<Outcome, Self::Error> {
69 Ok(Outcome::Fulfilled)
70 }
71 }
72
73 struct IdentityExecutor<E> {
74 inner: E,
75 }
76 impl<E: Executor> Executor for IdentityExecutor<E> {
77 type Error = E::Error;
78 fn execute(&mut self, execution: Execution) -> Result<Outcome, Self::Error> {
79 self.inner.execute(execution)
80 }
81 }
82
83 struct IdentityMiddleware;
84 impl<E: Executor> Middleware<E> for IdentityMiddleware {
85 type Executor = IdentityExecutor<E>;
86 fn wrap(&self, executor: E) -> Self::Executor {
87 IdentityExecutor { inner: executor }
88 }
89 }
90
91 struct BreachExecutor<E> {
92 _inner: E,
93 }
94 impl<E: Executor> Executor for BreachExecutor<E> {
95 type Error = E::Error;
96 fn execute(&mut self, _execution: Execution) -> Result<Outcome, Self::Error> {
97 Ok(Outcome::Breached)
98 }
99 }
100
101 struct BreachMiddleware;
102 impl<E: Executor> Middleware<E> for BreachMiddleware {
103 type Executor = BreachExecutor<E>;
104 fn wrap(&self, executor: E) -> Self::Executor {
105 BreachExecutor { _inner: executor }
106 }
107 }
108
109 fn dummy_execution() -> Execution {
110 Execution::new(Pact::new(
111 Default::default(),
112 "dummy_docket".to_string(),
113 "dummy_kind".to_string(),
114 vec![],
115 ))
116 }
117
118 #[test]
119 fn identity_middleware_preserves_fulfilled() {
120 let middleware = IdentityMiddleware;
121 let mut executor = middleware.wrap(DummyExecutor);
122 let outcome = executor.execute(dummy_execution()).unwrap();
123 assert_eq!(outcome, Outcome::Fulfilled);
124 }
125
126 #[test]
127 fn breach_middleware_alters_outcome() {
128 let middleware = BreachMiddleware;
129 let mut executor = middleware.wrap(DummyExecutor);
130 let outcome = executor.execute(dummy_execution()).unwrap();
131 assert_eq!(outcome, Outcome::Breached);
132 }
133
134 #[test]
135 fn stacked_middleware_composes() {
136 let inner = IdentityMiddleware.wrap(DummyExecutor);
141 let mut stacked = IdentityMiddleware.wrap(inner);
142 let outcome = stacked.execute(dummy_execution()).unwrap();
143 assert_eq!(outcome, Outcome::Fulfilled);
144 }
145
146 #[test]
147 fn stacked_middleware_preserves_ordering() {
148 let inner = IdentityMiddleware.wrap(DummyExecutor);
151 let mut stacked = BreachMiddleware.wrap(inner);
152 let outcome = stacked.execute(dummy_execution()).unwrap();
153 assert_eq!(outcome, Outcome::Breached);
154 }
155}