Skip to main content

datex_core/network/com_hub/
metadata.rs

1use log::info;
2
3use crate::{
4    collections::HashMap,
5    network::{
6        com_hub::{
7            ComHub, managers::socket_manager::DynamicEndpointProperties,
8        },
9        com_interfaces::com_interface::ComInterfaceUUID,
10    },
11};
12
13use crate::{
14    network::com_interfaces::com_interface::properties::{
15        ComInterfaceProperties, InterfaceDirection,
16    },
17    values::core_values::endpoint::Endpoint,
18};
19
20use crate::{
21    network::com_hub::managers::com_interface_manager::InterfaceInfo,
22    prelude::*,
23};
24use core::fmt::Display;
25use itertools::Itertools;
26use serde::{Deserialize, Serialize};
27
28#[derive(Serialize, Deserialize, Debug)]
29#[cfg_attr(feature = "wasm_runtime", derive(tsify::Tsify))]
30pub struct ComHubMetadataInterfaceSocket {
31    pub uuid: String,
32    pub direction: InterfaceDirection,
33    pub endpoint: Option<Endpoint>,
34    pub properties: Option<DynamicEndpointProperties>,
35}
36
37#[derive(Serialize, Deserialize)]
38#[cfg_attr(feature = "wasm_runtime", derive(tsify::Tsify))]
39pub struct ComHubMetadataInterfaceSocketWithoutEndpoint {
40    pub uuid: String,
41    pub direction: InterfaceDirection,
42}
43
44#[derive(Serialize, Deserialize, Debug)]
45#[cfg_attr(feature = "wasm_runtime", derive(tsify::Tsify))]
46pub struct ComHubMetadataInterface {
47    pub uuid: String,
48    pub properties: ComInterfaceProperties,
49    pub sockets: Vec<ComHubMetadataInterfaceSocket>,
50    pub is_waiting_for_socket_connections: bool,
51}
52
53#[derive(Serialize, Deserialize, Debug)]
54#[cfg_attr(feature = "wasm_runtime", derive(tsify::Tsify))]
55pub struct ComHubMetadata {
56    pub endpoint: Endpoint,
57    pub interfaces: Vec<ComHubMetadataInterface>,
58}
59
60impl Display for ComHubMetadata {
61    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
62        writeln!(f, "ComHub ({})", self.endpoint)?;
63
64        // print interfaces
65        for interface in &self.interfaces {
66            writeln!(
67                f,
68                "  {}/{}{}{}:",
69                interface.properties.interface_type,
70                interface.properties.channel,
71                if interface.is_waiting_for_socket_connections {
72                    " [accepting connections]"
73                } else {
74                    ""
75                },
76                interface
77                    .properties
78                    .name
79                    .clone()
80                    .map(|n| format!(" ({n})"))
81                    .unwrap_or("".to_string()),
82            )?;
83
84            // print sockets
85            let sorted_sockets = interface.sockets.iter().sorted_by_key(|s| {
86                match &s.properties {
87                    Some(properties) => properties.distance,
88                    None => i8::MAX,
89                }
90            });
91
92            for socket in sorted_sockets {
93                writeln!(
94                    f,
95                    "   {} {}{} (distance: {}, uuid: {})",
96                    match socket.direction {
97                        InterfaceDirection::In => "──▶".to_string(),
98                        InterfaceDirection::Out => "◀──".to_string(),
99                        InterfaceDirection::InOut => "◀──▶".to_string(),
100                    },
101                    match &socket.properties {
102                        Some(properties) => match properties.is_direct {
103                            true => "".to_string(),
104                            false => "[INDIRECT] ".to_string(),
105                        },
106                        None => "".to_string(),
107                    },
108                    match &socket.endpoint {
109                        Some(endpoint) => endpoint.to_string(),
110                        None => "unknown".to_string(),
111                    },
112                    match &socket.properties {
113                        Some(properties) => properties.distance.to_string(),
114                        None => "unknown".to_string(),
115                    },
116                    socket.uuid
117                )?;
118            }
119        }
120
121        Ok(())
122    }
123}
124
125impl ComHub {
126    /// Generates metadata about the ComHub, its interfaces and sockets.
127    pub fn get_metadata(&self) -> ComHubMetadata {
128        let mut metadata = ComHubMetadata {
129            endpoint: self.endpoint.clone(),
130            interfaces: Vec::new(),
131        };
132
133        let mut sockets_by_com_interface_uuid: HashMap<
134            ComInterfaceUUID,
135            Vec<ComHubMetadataInterfaceSocket>,
136        > = HashMap::new();
137
138        for (endpoint, sockets) in
139            self.socket_manager.endpoint_sockets.borrow().iter()
140        {
141            for (socket_uuid, properties) in sockets {
142                let socket = self
143                    .socket_manager
144                    .get_socket_by_uuid(socket_uuid)
145                    .unwrap();
146                let com_interface_uuid = socket.interface_uuid.clone();
147                if !sockets_by_com_interface_uuid
148                    .contains_key(&com_interface_uuid)
149                {
150                    sockets_by_com_interface_uuid
151                        .insert(com_interface_uuid.clone(), Vec::new());
152                }
153                sockets_by_com_interface_uuid
154                    .get_mut(&com_interface_uuid)
155                    .unwrap()
156                    .push(ComHubMetadataInterfaceSocket {
157                        uuid: socket_uuid.to_string(),
158                        endpoint: Some(endpoint.clone()),
159                        direction: socket.socket_properties.direction.clone(),
160                        properties: Some(properties.clone()),
161                    });
162            }
163        }
164
165        for (socket_uuid, socket) in self.socket_manager.sockets.borrow().iter()
166        {
167            // if no endpoints are registered, we consider it a socket without an endpoint
168            if socket.endpoints.is_empty() {
169                let com_interface_uuid = socket.interface_uuid.clone();
170                if !sockets_by_com_interface_uuid
171                    .contains_key(&com_interface_uuid)
172                {
173                    sockets_by_com_interface_uuid
174                        .insert(com_interface_uuid.clone(), Vec::new());
175                }
176                sockets_by_com_interface_uuid
177                    .get_mut(&com_interface_uuid)
178                    .unwrap()
179                    .push(ComHubMetadataInterfaceSocket {
180                        uuid: socket_uuid.to_string(),
181                        direction: socket.socket_properties.direction.clone(),
182                        endpoint: None,
183                        properties: None,
184                    });
185                continue;
186            }
187        }
188
189        for (
190            uuid,
191            InterfaceInfo {
192                properties,
193                is_waiting_for_socket_connections,
194                ..
195            },
196        ) in self.interfaces_manager.interfaces.borrow().iter()
197        {
198            metadata.interfaces.push(ComHubMetadataInterface {
199                uuid: uuid.to_string(),
200                properties: properties.as_ref().clone(),
201                sockets: sockets_by_com_interface_uuid
202                    .remove(uuid)
203                    .unwrap_or_default(),
204                is_waiting_for_socket_connections:
205                    *is_waiting_for_socket_connections,
206            });
207        }
208
209        metadata
210    }
211
212    /// Prints the ComHub metadata to the log.
213    pub fn print_metadata(&self) {
214        let metadata = self.get_metadata();
215        info!("ComHub Metadata:\n{metadata}");
216    }
217}