cog_task/action/core/
merge.rs

1use crate::action::{Action, ActionSignal, Props, StatefulAction, INFINITE};
2use crate::comm::{QWriter, Signal, SignalId};
3use crate::resource::{IoManager, ResourceManager};
4use crate::server::{AsyncSignal, Config, State, SyncSignal};
5use eyre::{eyre, Result};
6use serde::{Deserialize, Serialize};
7use std::collections::{BTreeMap, BTreeSet};
8
9#[derive(Debug, Deserialize, Serialize)]
10pub struct Merge {
11    in_many: BTreeSet<SignalId>,
12    out_one: SignalId,
13}
14
15stateful!(Merge {
16    in_many: BTreeSet<SignalId>,
17    out_one: SignalId,
18});
19
20impl Action for Merge {
21    #[inline]
22    fn in_signals(&self) -> BTreeSet<SignalId> {
23        self.in_many.clone()
24    }
25
26    #[inline]
27    fn out_signals(&self) -> BTreeSet<SignalId> {
28        BTreeSet::from([self.out_one])
29    }
30
31    fn init(self) -> Result<Box<dyn Action>>
32    where
33        Self: 'static + Sized,
34    {
35        if self.in_many.is_empty() {
36            Err(eyre!("Merge with no inputs is useless."))
37        } else if self.out_one == 0 {
38            Err(eyre!("Merge without an output is useless."))
39        } else if self.in_many.contains(&self.out_one) {
40            Err(eyre!("Merge output cannot be connected to its input."))
41        } else {
42            Ok(Box::new(self))
43        }
44    }
45
46    fn stateful(
47        &self,
48        _io: &IoManager,
49        _res: &ResourceManager,
50        _config: &Config,
51        _sync_writer: &QWriter<SyncSignal>,
52        _async_writer: &QWriter<AsyncSignal>,
53    ) -> Result<Box<dyn StatefulAction>> {
54        Ok(Box::new(StatefulMerge {
55            done: false,
56            in_many: self.in_many.clone(),
57            out_one: self.out_one,
58        }))
59    }
60}
61
62impl StatefulAction for StatefulMerge {
63    impl_stateful!();
64
65    fn props(&self) -> Props {
66        INFINITE.into()
67    }
68
69    fn update(
70        &mut self,
71        signal: &ActionSignal,
72        _sync_writer: &mut QWriter<SyncSignal>,
73        _async_writer: &mut QWriter<AsyncSignal>,
74        state: &State,
75    ) -> Result<Signal> {
76        if let ActionSignal::StateChanged(_, signal) = signal {
77            let mut news = BTreeMap::new();
78            for id in signal.iter().filter(|&i| self.in_many.contains(i)) {
79                if let Some(value) = state.get(id) {
80                    news.insert(self.out_one, value.clone());
81                }
82            }
83
84            Ok(Signal::new(news))
85        } else {
86            Ok(Signal::none())
87        }
88    }
89}