Skip to main content

datex_core/network/com_hub/
metadata.rs

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