Skip to main content

rsiot/components_config/http_server/
get_endpoint.rs

1//! Структура хранения данных точки GET
2
3use std::fmt::Debug;
4
5use serde::{Serialize, de::DeserializeOwned};
6
7use crate::{
8    message::MsgDataBound,
9    serde_utils::{self, SerdeAlg, SerdeAlgKind},
10};
11
12// ANCHOR: GetEndpointConfig
13/// Конфигурация отдельной точки GET
14#[derive(Clone, Debug)]
15pub struct GetEndpointConfig<TMsg, TServerToClient> {
16    /// Алгоритм сериализации / десериализации
17    pub serde_alg: SerdeAlgKind,
18
19    /// Путь
20    ///
21    /// Примеры:
22    ///
23    /// ```rust
24    /// path: `/data`
25    /// ```
26    pub path: &'static str,
27
28    /// Данные для точки GET
29    ///
30    /// На входной структуре необходимо реализовать:
31    ///
32    /// ```rust
33    /// #[derive(Clone, Debug, Default, Deserialize, Serialize)]
34    /// ```
35    pub server_to_client_data: TServerToClient,
36
37    /// Функция обновления данных на основе входящих сообщений
38    pub fn_input: fn(&TMsg, &mut TServerToClient),
39}
40// ANCHOR: GetEndpointConfig
41
42impl<TMsg, TServerToClient> GetEndpoint<TMsg> for GetEndpointConfig<TMsg, TServerToClient>
43where
44    TMsg: 'static + MsgDataBound,
45    TServerToClient: 'static + Clone + Debug + DeserializeOwned + Serialize + Send + Sync,
46{
47    fn get_path(&self) -> &str {
48        self.path
49    }
50
51    fn fn_input(&mut self, msg: &TMsg) {
52        (self.fn_input)(msg, &mut self.server_to_client_data)
53    }
54
55    fn serialize(&self) -> Result<Vec<u8>, serde_utils::Error> {
56        let serde_alg = SerdeAlg::new(self.serde_alg);
57        serde_alg.serialize(&self.server_to_client_data)
58    }
59
60    fn clone_dyn(&self) -> Box<dyn GetEndpoint<TMsg>> {
61        Box::new(self.clone())
62    }
63}
64
65/// Трейт для обеспечения логики работы отдельной точки GET
66///
67/// В разных точках хранят данные в разных структурах (поле `data`). Трейт нужен для обработки в
68/// массиве
69pub trait GetEndpoint<TMsg>
70where
71    Self: Debug + Send + Sync,
72{
73    /// Получить путь для роутера
74    fn get_path(&self) -> &str;
75
76    /// Сериализация данных
77    fn serialize(&self) -> Result<Vec<u8>, serde_utils::Error>;
78
79    /// Обновление данных на основе входящих сообщений
80    fn fn_input(&mut self, msg: &TMsg);
81
82    /// Поддержка клонирования
83    fn clone_dyn(&self) -> Box<dyn GetEndpoint<TMsg>>;
84}
85
86impl<TMsg> Clone for Box<dyn GetEndpoint<TMsg>> {
87    fn clone(&self) -> Self {
88        self.clone_dyn()
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    use std::collections::HashMap;
97
98    use serde::{Deserialize, Serialize};
99
100    use crate::message::example_message::Custom;
101
102    #[test]
103    fn test1() {
104        let mut vec_trait: Vec<Box<dyn GetEndpoint<Custom>>> = vec![];
105
106        #[derive(Clone, Debug, Deserialize, Serialize)]
107        struct Data1 {}
108
109        #[derive(Clone, Debug, Deserialize, Serialize)]
110        struct Data2 {}
111
112        let end1 = GetEndpointConfig {
113            serde_alg: SerdeAlgKind::Unspecified,
114            path: "/1",
115            server_to_client_data: Data1 {},
116            fn_input: |_, _| (),
117        };
118        let end2 = GetEndpointConfig {
119            serde_alg: SerdeAlgKind::Unspecified,
120            path: "/2",
121            server_to_client_data: Data2 {},
122            fn_input: |_, _| (),
123        };
124        vec_trait.push(Box::new(end1));
125        vec_trait.push(Box::new(end2));
126
127        // Собираем в словарь
128        let mut map = HashMap::new();
129
130        for e in vec_trait.into_iter() {
131            let endpoint = e.get_path().to_string();
132            map.insert(endpoint, e);
133        }
134    }
135}