1use std::cell::RefCell;
2use std::fmt::Debug;
3use std::ops::{Deref, DerefMut};
4use std::rc::Rc;
5use std::sync::{Arc, RwLock};
6use std::time::{Duration, Instant};
7
8use camino::Utf8Path;
9use cpclib_asm::EnvEventObserver;
10use cpclib_runner::event::EventObserver;
11
12use crate::task::Task;
13
14#[derive(Clone, Debug)]
15pub enum BndBuilderState<'a> {
16 ComputeDependencies(&'a Utf8Path),
17 RunTasks,
18 Finish
19}
20
21#[derive(Clone)]
22pub enum BndBuilderEvent<'a> {
23 ChangeState(BndBuilderState<'a>),
24 StartRule {
25 rule: &'a Utf8Path,
26 nb: usize,
27 out_of: usize
28 },
29 StopRule(&'a Utf8Path),
30 FailedRule(&'a Utf8Path),
31 StartTask(Option<&'a Utf8Path>, &'a Task),
32 StopTask(Option<&'a Utf8Path>, &'a Task, Duration),
33 TaskStdout(&'a Utf8Path, &'a Task, &'a str),
34 TaskStderr(&'a Utf8Path, &'a Task, &'a str),
35 Stdout(&'a str),
36 Stderr(&'a str)
37}
38
39pub trait BndBuilderObserver: EventObserver + EnvEventObserver {
40 fn update(&mut self, event: BndBuilderEvent);
41}
42
43impl<T: BndBuilderObserver> BndBuilderObserver for Box<T> {
44 fn update(&mut self, event: BndBuilderEvent) {
45 self.deref_mut().update(event)
46 }
47}
48
49impl<T: BndBuilderObserver> BndBuilderObserver for Arc<T> {
50 fn update(&mut self, event: BndBuilderEvent) {
51 Arc::<T>::get_mut(self).unwrap().update(event)
52 }
53}
54
55pub trait BndBuilderObserved: Debug + Sync + Send {
56 #[inline]
57 fn emit_stdout<S: AsRef<str>>(&self, s: S) {
58 self.notify(BndBuilderEvent::Stdout(s.as_ref()))
59 }
60 #[inline]
61 fn emit_stderr<S: AsRef<str>>(&self, s: S) {
62 self.notify(BndBuilderEvent::Stderr(s.as_ref()))
63 }
64 #[inline]
65 fn emit_task_stdout<S: AsRef<str>, P: AsRef<Utf8Path>>(&self, p: P, t: &Task, s: S) {
66 self.notify(BndBuilderEvent::TaskStdout(p.as_ref(), t, s.as_ref()))
67 }
68 #[inline]
69 fn emit_task_stderr<S: AsRef<str>, P: AsRef<Utf8Path>>(&self, p: P, t: &Task, s: S) {
70 self.notify(BndBuilderEvent::TaskStderr(p.as_ref(), t, s.as_ref()))
71 }
72 #[inline]
73 fn do_compute_dependencies<P: AsRef<Utf8Path>>(&self, p: P) {
74 self.notify(BndBuilderEvent::ChangeState(
75 BndBuilderState::ComputeDependencies(p.as_ref())
76 ))
77 }
78 #[inline]
79 fn do_run_tasks(&self) {
80 self.notify(BndBuilderEvent::ChangeState(BndBuilderState::RunTasks))
81 }
82 #[inline]
83 fn do_finish(&self) {
84 self.notify(BndBuilderEvent::ChangeState(BndBuilderState::Finish))
85 }
86 #[inline]
87 fn start_rule<P: AsRef<Utf8Path>>(&self, rule: P, nb: usize, out_of: usize) {
88 self.notify(BndBuilderEvent::StartRule {
89 rule: rule.as_ref(),
90 nb,
91 out_of
92 })
93 }
94 #[inline]
95 fn stop_rule<P: AsRef<Utf8Path>>(&self, task: P) {
96 self.notify(BndBuilderEvent::StopRule(task.as_ref()))
97 }
98 #[inline]
99 fn failed_rule<P: AsRef<Utf8Path>>(&self, task: P) {
100 self.notify(BndBuilderEvent::FailedRule(task.as_ref()))
101 }
102 #[inline]
103 fn start_task(&self, rule: Option<&Utf8Path>, task: &Task) {
104 self.notify(BndBuilderEvent::StartTask(rule, task))
105 }
106 #[inline]
107 fn stop_task(&self, rule: Option<&Utf8Path>, task: &Task, duration: Duration) {
108 self.notify(BndBuilderEvent::StopTask(rule, task, duration))
109 }
110 #[inline]
111 fn notify(&self, event: BndBuilderEvent<'_>) {
112 let observers = self.observers().clone();
113 for observer in observers.iter() {
114 observer.update(event.clone());
115 }
116 }
117 fn observers(&self) -> Arc<ListOfBndBuilderObserverRc>;
118 fn add_observer(&mut self, observer: BndBuilderObserverRc);
119}
120
121#[derive(Debug, Clone)]
122pub struct BndBuilderObserverRc(pub(crate) Arc<RwLock<dyn BndBuilderObserver + Sync + Send>>);
123#[derive(Clone, Debug)]
124pub struct ListOfBndBuilderObserverRc(Vec<BndBuilderObserverRc>);
125
126impl BndBuilderObserverRc {
127 pub fn new<O: BndBuilderObserver + Sized + 'static + Sync + Send>(observer: O) -> Self {
128 let observer = RwLock::new(observer);
129 let observer = Arc::new(observer);
130 Self(observer)
131 }
132
133 pub fn new_default() -> Self {
134 let observer = BndBuilderDefaultObserver::default();
135 Self::new(observer)
136 }
137
138 pub fn update(&self, event: BndBuilderEvent) {
139 self.0.deref().write().unwrap().deref_mut().update(event);
140 }
141}
142
143impl ListOfBndBuilderObserverRc {
144 pub fn iter(&self) -> ListOfBndBuilderObserverRcIter {
145 ListOfBndBuilderObserverRcIter { list: self, idx: 0 }
146 }
147
148 pub fn add_observer(&mut self, o: BndBuilderObserverRc) {
149 self.0.push(o);
150 }
151}
152
153pub struct ListOfBndBuilderObserverRcIter<'l> {
154 list: &'l ListOfBndBuilderObserverRc,
155 idx: usize
156}
157
158impl Iterator for ListOfBndBuilderObserverRcIter<'_> {
159 type Item = BndBuilderObserverRc;
160
161 fn next(&mut self) -> Option<Self::Item> {
162 let vec = self.list.0.deref();
163 if self.idx == vec.len() {
164 None
165 }
166 else {
167 let res = vec.get(self.idx).cloned();
168 self.idx += 1;
169 res
170 }
171 }
172}
173
174impl Deref for BndBuilderObserverRc {
175 type Target = Arc<RwLock<dyn BndBuilderObserver + Sync + Send>>;
176
177 fn deref(&self) -> &Self::Target {
178 &self.0
179 }
180}
181
182impl DerefMut for BndBuilderObserverRc {
183 fn deref_mut(&mut self) -> &mut Self::Target {
184 &mut self.0
185 }
186}
187
188impl From<Vec<BndBuilderObserverRc>> for ListOfBndBuilderObserverRc {
189 fn from(value: Vec<BndBuilderObserverRc>) -> Self {
190 Self(value)
191 }
192}
193
194impl Deref for ListOfBndBuilderObserverRc {
195 type Target = Vec<BndBuilderObserverRc>;
196
197 fn deref(&self) -> &Self::Target {
198 &self.0
199 }
200}
201
202impl DerefMut for ListOfBndBuilderObserverRc {
203 fn deref_mut(&mut self) -> &mut Self::Target {
204 &mut self.0
205 }
206}
207
208impl Default for ListOfBndBuilderObserverRc {
209 fn default() -> Self {
210 Self(Vec::with_capacity(1))
211 }
212}
213
214impl EventObserver for ListOfBndBuilderObserverRc {
215 fn emit_stdout(&self, s: &str) {
216 for observer in self.0.clone().into_iter() {
217 observer.0.deref().read().unwrap().emit_stdout(s);
218 }
219 }
220
221 fn emit_stderr(&self, s: &str) {
222 for observer in self.0.clone().into_iter() {
223 observer.0.deref().read().unwrap().emit_stderr(s);
224 }
225 }
226}
227
228impl BndBuilderObserver for ListOfBndBuilderObserverRc {
229 fn update(&mut self, event: BndBuilderEvent) {
230 for observer in self.0.clone().into_iter() {
231 let mut observer = observer.0.deref().write().unwrap();
232 observer.update(event.clone());
233 }
234 }
235}
236
237#[derive(Debug, Clone)]
238pub struct RuleTaskEventDispatcher<'observed, 'rule, 'task, E>
239where E: BndBuilderObserved
240{
241 observed: &'observed E,
242 rule: Option<&'rule Utf8Path>,
243 task: &'task Task,
244 start: std::time::Instant
245}
246
247impl<E> Drop for RuleTaskEventDispatcher<'_, '_, '_, E>
266where E: BndBuilderObserved
267{
268 fn drop(&mut self) {
269 self.observed
270 .stop_task(self.rule, self.task, std::time::Instant::now() - self.start);
271 }
272}
273
274impl<'observed, 'rule, 'task, E> RuleTaskEventDispatcher<'observed, 'rule, 'task, E>
275where E: BndBuilderObserved
276{
277 #[inline]
278 pub fn new(builder: &'observed E, rule: &'rule Utf8Path, task: &'task Task) -> Self {
279 builder.start_task(Some(rule), task);
280 Self {
281 observed: builder,
282 rule: Some(rule),
283 task,
284 start: Instant::now()
285 }
286 }
287
288 #[inline]
289 pub fn new_alone(observed: &'observed E, task: &'task Task) -> Self {
290 observed.start_task(None, task);
291 Self {
292 observed,
293 rule: None,
294 task,
295 start: Instant::now()
296 }
297 }
298}
299
300impl<E> EventObserver for RuleTaskEventDispatcher<'_, '_, '_, E>
301where E: BndBuilderObserved + Sync
302{
303 #[inline]
304 fn emit_stdout(&self, s: &str) {
305 match self.rule {
306 Some(rule) => self.observed.emit_task_stdout(rule, self.task, s),
307 None => self.observed.emit_stdout(s)
308 }
309 }
310
311 #[inline]
312 fn emit_stderr(&self, s: &str) {
313 match self.rule {
314 Some(rule) => self.observed.emit_task_stderr(rule, self.task, s),
315 None => self.observed.emit_stderr(s)
316 }
317 }
318}
319
320impl<E> BndBuilderObserver for RuleTaskEventDispatcher<'_, '_, '_, E>
321where E: BndBuilderObserved
322{
323 fn update(&mut self, event: BndBuilderEvent) {
324 unreachable!()
325 }
326}
327
328#[derive(Default, Debug)]
329pub struct BndBuilderDefaultObserver {}
330
331impl BndBuilderDefaultObserver {
332 pub fn new() -> Rc<RefCell<Box<dyn BndBuilderObserver>>> {
333 Rc::new(RefCell::new(Box::new(BndBuilderDefaultObserver {})))
334 }
335}
336
337impl EventObserver for BndBuilderDefaultObserver {
338 fn emit_stdout(&self, s: &str) {
339 print!("{s}");
340 }
341
342 fn emit_stderr(&self, s: &str) {
343 eprint!("{s}");
344 }
345}
346
347impl BndBuilderObserver for BndBuilderDefaultObserver {
348 fn update(&mut self, event: BndBuilderEvent) {
349 match event {
350 BndBuilderEvent::ChangeState(s) => {
351 match s {
352 BndBuilderState::ComputeDependencies(p) => {
353 println!("> Compute dependencies for rule `{p}`")
354 },
355 BndBuilderState::RunTasks => println!("> Execute tasks"),
356 BndBuilderState::Finish => println!("> Done.")
357 }
358 },
359 BndBuilderEvent::StartRule { rule, nb, out_of } => {
360 println!("[{nb}/{out_of}] Handle {rule}")
361 },
362 BndBuilderEvent::StopRule(_) => {},
363 BndBuilderEvent::FailedRule(_) => todo!(),
364 BndBuilderEvent::StartTask(r, t) => {
365 println!("\t$ {t}");
366 },
367 BndBuilderEvent::StopTask(r, t, d) => {
368 println!(
369 "\tElapsed time: {}",
370 fancy_duration::FancyDuration(d).truncate(1)
371 )
372 },
373 BndBuilderEvent::TaskStdout(tgt, task, txt) => {
374 for line in txt.lines() {
375 println!("[{tgt}]\t{line}")
376 }
377 },
378 BndBuilderEvent::TaskStderr(tgt, task, txt) => {
379 for line in txt.lines() {
380 eprintln!("[{tgt}]\t{line}")
381 }
382 },
383 BndBuilderEvent::Stdout(s) => print!("{s}"),
384 BndBuilderEvent::Stderr(s) => print!("{s}")
385 }
386 }
387}