1use dope_core::driver::storage;
2
3use crate::{
4 executor::{self, session},
5 shutdown,
6 topology::{self, Worker, lending, recipe},
7};
8
9pub trait Operation<'d, C>: Sized {
11 type Output;
12
13 fn run(self, context: C) -> Self::Output
14 where
15 Self: 'd;
16}
17
18impl<'d, C, F, R> Operation<'d, C> for F
19where
20 F: FnOnce(C) -> R,
21{
22 type Output = R;
23
24 fn run(self, context: C) -> Self::Output
25 where
26 Self: 'd,
27 {
28 self(context)
29 }
30}
31
32impl<S, I, Q, O, R> executor::Op<S, Q> for (I, O)
33where
34 S: storage::Plan,
35 O: for<'scope, 'life, 'p, 'd> Operation<'d, Worker<'scope, 'life, 'p, 'd, S, I, Q>, Output = R>,
36{
37 type Output = R;
38
39 fn run<'scope, 'life, 'p, 'd>(
40 self,
41 session: session::Scope<'scope, 'life, 'p, 'd, S, Q>,
42 ) -> Self::Output
43 where
44 'd: 'p,
45 'p: 'life,
46 'd: 'life,
47 'life: 'scope,
48 Self: 'd,
49 S: 'd,
50 Q: 'd,
51 {
52 self.1.run(Worker::new(session, self.0))
53 }
54}
55
56pub struct Map<O, F>(pub O, pub F);
58
59impl<'d, C, O, F, R> Operation<'d, C> for Map<O, F>
60where
61 O: Operation<'d, C>,
62 F: FnOnce(O::Output) -> R,
63{
64 type Output = R;
65
66 fn run(self, context: C) -> R
67 where
68 Self: 'd,
69 {
70 (self.1)(self.0.run(context))
71 }
72}
73
74pub struct Compose;
76
77impl<'scope, 'life, 'p, 'd, S, I, T, Q> Operation<'d, Worker<'scope, 'life, 'p, 'd, S, (I, T), Q>>
78 for Compose
79where
80 S: storage::Plan,
81 Q: executor::Startup,
82 I: lending::ComposeFrom<S, T, Q>,
83{
84 type Output = Result<I::Output, I::Error>;
85
86 fn run(self, worker: Worker<'scope, 'life, 'p, 'd, S, (I, T), Q>) -> Self::Output
87 where
88 Self: 'd,
89 {
90 worker.lend(|(head, tail), stage| head.compose(tail, stage))
91 }
92}
93
94pub struct Run<'report>(pub &'report mut session::Completion);
96
97impl<'report, 'scope, 'life, 'p, 'd, S, I, Q> Operation<'d, Worker<'scope, 'life, 'p, 'd, S, I, Q>>
98 for Run<'report>
99where
100 S: storage::Plan,
101 Q: executor::Startup,
102 I: recipe::Execute<S>,
103{
104 type Output = Result<
105 shutdown::Requested<Q>,
106 topology::Failure<'report, I::Error, shutdown::Requested<Q>>,
107 >;
108
109 fn run(self, worker: Worker<'scope, 'life, 'p, 'd, S, I, Q>) -> Self::Output
110 where
111 Self: 'd,
112 {
113 worker.lend(|source, stage| source.execute(stage, self.0))
114 }
115}