rsiot/executor/component/
single_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, TMessage>
9where
10    TMessage: MsgDataBound,
11{
12    in_out: Option<CmpInOut<TMessage>>,
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            in_out: None,
24            config: Some(config.into()),
25        }
26    }
27}
28
29#[async_trait(?Send)]
30impl<TConfig, TMsg> IComponent<TMsg> for Component<TConfig, TMsg>
31where
32    Self: IComponentProcess<TConfig, TMsg>,
33    TMsg: MsgDataBound,
34{
35    fn set_interface(&mut self, in_out: CmpInOut<TMsg>) {
36        self.in_out = Some(in_out);
37    }
38
39    async fn spawn(&mut self) -> CmpResult {
40        let in_out = self
41            .in_out
42            .take()
43            .ok_or(ComponentError::Initialization("input not set".into()))?;
44
45        let config = self
46            .config
47            .take()
48            .ok_or(ComponentError::Initialization("config not set".into()))?;
49
50        self.process(config, in_out).await
51    }
52}
53
54/// Трейт основной функции компонента
55///
56/// Каждый компонент должен определить данный трейт
57#[async_trait(?Send)]
58pub trait IComponentProcess<TConfig, TMsg>
59where
60    TMsg: MsgDataBound,
61{
62    /// Основная функция компонента
63    async fn process(&self, config: TConfig, in_out: CmpInOut<TMsg>) -> CmpResult;
64}
65
66/// Интерфейс компонента, который используется исполнитель при добавлении компонентов
67#[async_trait(?Send)]
68pub trait IComponent<TMsg>
69where
70    TMsg: MsgDataBound,
71{
72    fn set_interface(&mut self, in_out: CmpInOut<TMsg>);
73
74    async fn spawn(&mut self) -> CmpResult;
75}