trellis_runner/runner/
builder.rs

1use num_traits::float::FloatCore;
2
3use super::{Error, InitialiseRunner, Runner};
4use crate::{
5    watchers::{Frequency, Observable, Observer, ObserverVec},
6    Calculation, Control, Problem, State, UserState,
7};
8
9pub trait GenerateBuilder<P, S>: Sized + Calculation<P, S>
10where
11    S: UserState,
12{
13    fn build_for(self, problem: P) -> Builder<Self, P, S, ()>;
14}
15
16impl<C, P, S> GenerateBuilder<P, S> for C
17where
18    C: Calculation<P, S>,
19    S: UserState,
20    <S as UserState>::Float: FloatCore,
21{
22    fn build_for(self, problem: P) -> Builder<Self, P, S, ()> {
23        Builder {
24            problem,
25            calculation: self,
26            state: State::new(),
27            time: true,
28            cancellation_token: (),
29            observers: ObserverVec::default(),
30        }
31    }
32}
33
34pub struct Builder<C, P, S, T>
35where
36    C: Calculation<P, S>,
37    S: UserState,
38{
39    calculation: C,
40    problem: P,
41    state: State<S>,
42    time: bool,
43    cancellation_token: T,
44    observers: ObserverVec<State<S>>,
45}
46impl<C, P, S, R> Builder<C, P, S, R>
47where
48    C: Calculation<P, S>,
49    S: UserState,
50{
51    #[must_use]
52    pub fn time(mut self, time: bool) -> Self {
53        self.time = time;
54        self
55    }
56
57    /// Configure the attached state.
58    ///
59    /// Apply any runtime configuration option to the attached state.
60    #[must_use]
61    pub fn configure<F: FnOnce(State<S>) -> State<S>>(mut self, configure: F) -> Self {
62        let state = configure(self.state);
63        self.state = state;
64        self
65    }
66
67    #[must_use]
68    pub fn attach_observer<OBS: Observer<State<S>> + 'static>(
69        mut self,
70        observer: OBS,
71        frequency: Frequency,
72    ) -> Self {
73        self.observers.attach(
74            std::sync::Arc::new(std::sync::Mutex::new(observer)),
75            frequency,
76        );
77        self
78    }
79}
80
81impl<C, P, S> Builder<C, P, S, ()>
82where
83    C: Calculation<P, S>,
84    S: UserState,
85{
86    #[must_use]
87    pub fn with_cancellation_token<T>(self, cancellation_token: T) -> Builder<C, P, S, T> {
88        Builder {
89            calculation: self.calculation,
90            problem: self.problem,
91            state: self.state,
92            time: self.time,
93            cancellation_token,
94            observers: self.observers,
95        }
96    }
97
98    pub fn finalise(self) -> Result<Runner<C, P, S, ()>, Error>
99    where
100        C: Calculation<P, S>,
101        S: UserState,
102    {
103        let mut runner = Runner {
104            problem: Problem::new(self.problem),
105            calculation: self.calculation,
106            state: Some(self.state),
107            time: self.time,
108            cancellation_token: None,
109            signals: vec![],
110            observers: self.observers,
111        };
112        runner.initialise_controllers()?;
113        Ok(runner)
114    }
115}
116
117impl<C, P, S, T> Builder<C, P, S, T>
118where
119    T: Control + 'static,
120    C: Calculation<P, S>,
121    S: UserState,
122{
123    pub fn finalise(self) -> Result<Runner<C, P, S, T>, Error> {
124        let mut runner = Runner {
125            problem: Problem::new(self.problem),
126            calculation: self.calculation,
127            state: Some(self.state),
128            time: self.time,
129            cancellation_token: Some(self.cancellation_token),
130            signals: vec![],
131            observers: self.observers,
132        };
133        runner.initialise_controllers()?;
134        Ok(runner)
135    }
136}