rsiot/executor/component/
multi_thread.rs

1use async_trait::async_trait;
2
3use crate::message::MsgDataBound;
4
5use super::super::{CmpInOut, CmpResult, ComponentError};
6
7/// Представление обобщенного компонента
8pub struct Component<TConfig, TMsg>
9where
10    TMsg: MsgDataBound,
11{
12    in_out: Option<CmpInOut<TMsg>>,
13    config: Option<TConfig>,
14}
15
16impl<TConfig, TMsg> Component<TConfig, TMsg>
17where
18    TMsg: MsgDataBound,
19{
20    /// Создание компонента
21    pub fn new(config: impl Into<TConfig>) -> Self {
22        Self {
23            config: Some(config.into()),
24            in_out: None,
25        }
26    }
27}
28
29#[async_trait]
30impl<TConfig, TMsg> IComponent<TMsg> for Component<TConfig, TMsg>
31where
32    TMsg: MsgDataBound,
33    Self: IComponentProcess<TConfig, TMsg>,
34    TConfig: Send,
35{
36    fn set_interface(&mut self, in_out: CmpInOut<TMsg>) {
37        self.in_out = Some(in_out);
38    }
39
40    async fn spawn(&mut self) -> CmpResult {
41        let config = self
42            .config
43            .take()
44            .ok_or(ComponentError::Initialization("config not set".into()))?;
45
46        let in_out = self
47            .in_out
48            .take()
49            .ok_or(ComponentError::Initialization("in_out not set".into()))?;
50
51        self.process(config, in_out).await
52    }
53}
54
55/// Трейт основной функции компонента
56///
57/// Каждый компонент должен определить данный трейт
58#[async_trait]
59pub trait IComponentProcess<TConfig, TMsg>
60where
61    TMsg: MsgDataBound,
62{
63    /// Основная функция компонента
64    async fn process(&self, config: TConfig, in_out: CmpInOut<TMsg>) -> CmpResult;
65}
66
67/// Интерфейс компонента, который используется исполнитель при добавлении компонентов
68#[async_trait]
69pub trait IComponent<TMsg>
70where
71    TMsg: MsgDataBound,
72{
73    fn set_interface(&mut self, in_out: CmpInOut<TMsg>);
74
75    async fn spawn(&mut self) -> CmpResult;
76}