zerodds_corba_dds_bridge/
mapping.rs1use alloc::collections::BTreeMap;
11use alloc::string::String;
12use alloc::vec::Vec;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum Direction {
17 CorbaToDds,
19 DdsToCorba,
21 Bidirectional,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Default)]
28pub struct TopicQosRef {
29 pub reliability: Option<String>,
31 pub durability: Option<String>,
33 pub profile_name: Option<String>,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct OperationMapping {
40 pub operation: String,
42 pub request_topic: String,
44 pub reply_topic: String,
46 pub qos: TopicQosRef,
48}
49
50#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct BridgeRoute {
53 pub repository_id: String,
56 pub object_key: Vec<u8>,
58 pub direction: Direction,
60 pub operations: Vec<OperationMapping>,
62}
63
64impl BridgeRoute {
65 #[must_use]
67 pub fn operation(&self, name: &str) -> Option<&OperationMapping> {
68 self.operations.iter().find(|o| o.operation == name)
69 }
70}
71
72#[derive(Debug, Clone, Default)]
74pub struct BridgeMapping {
75 routes: BTreeMap<RouteKey, BridgeRoute>,
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
79struct RouteKey {
80 repository_id: String,
81 object_key: Vec<u8>,
82}
83
84impl BridgeMapping {
85 #[must_use]
87 pub fn new() -> Self {
88 Self::default()
89 }
90
91 pub fn add_route(&mut self, route: BridgeRoute) {
93 let key = RouteKey {
94 repository_id: route.repository_id.clone(),
95 object_key: route.object_key.clone(),
96 };
97 self.routes.insert(key, route);
98 }
99
100 #[must_use]
102 pub fn lookup(&self, repository_id: &str, object_key: &[u8]) -> Option<&BridgeRoute> {
103 let key = RouteKey {
104 repository_id: repository_id.into(),
105 object_key: object_key.to_vec(),
106 };
107 self.routes.get(&key)
108 }
109
110 #[must_use]
112 pub fn len(&self) -> usize {
113 self.routes.len()
114 }
115
116 #[must_use]
118 pub fn is_empty(&self) -> bool {
119 self.routes.is_empty()
120 }
121
122 #[must_use]
124 pub fn all_routes(&self) -> Vec<&BridgeRoute> {
125 self.routes.values().collect()
126 }
127}
128
129#[cfg(test)]
130#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
131mod tests {
132 use super::*;
133
134 fn echo_route() -> BridgeRoute {
135 BridgeRoute {
136 repository_id: "IDL:demo/Echo:1.0".into(),
137 object_key: alloc::vec![0xab],
138 direction: Direction::Bidirectional,
139 operations: alloc::vec![OperationMapping {
140 operation: "ping".into(),
141 request_topic: "demo/Echo/ping/Request".into(),
142 reply_topic: "demo/Echo/ping/Reply".into(),
143 qos: TopicQosRef {
144 reliability: Some("RELIABLE".into()),
145 durability: Some("VOLATILE".into()),
146 profile_name: None,
147 },
148 }],
149 }
150 }
151
152 #[test]
153 fn add_and_lookup_route() {
154 let mut m = BridgeMapping::new();
155 m.add_route(echo_route());
156 let r = m.lookup("IDL:demo/Echo:1.0", &[0xab]).unwrap();
157 assert_eq!(r.direction, Direction::Bidirectional);
158 assert_eq!(m.len(), 1);
159 }
160
161 #[test]
162 fn lookup_unknown_yields_none() {
163 let m = BridgeMapping::new();
164 assert!(m.lookup("IDL:demo/Echo:1.0", &[0xff]).is_none());
165 }
166
167 #[test]
168 fn operation_mapping_by_name() {
169 let r = echo_route();
170 let op = r.operation("ping").unwrap();
171 assert_eq!(op.request_topic, "demo/Echo/ping/Request");
172 assert_eq!(op.reply_topic, "demo/Echo/ping/Reply");
173 assert!(r.operation("nope").is_none());
174 }
175
176 #[test]
177 fn add_route_replaces_existing() {
178 let mut m = BridgeMapping::new();
179 m.add_route(echo_route());
180 let mut r2 = echo_route();
181 r2.direction = Direction::CorbaToDds;
182 m.add_route(r2);
183 assert_eq!(m.len(), 1);
184 assert_eq!(
185 m.lookup("IDL:demo/Echo:1.0", &[0xab]).unwrap().direction,
186 Direction::CorbaToDds
187 );
188 }
189
190 #[test]
191 fn all_routes_listing() {
192 let mut m = BridgeMapping::new();
193 m.add_route(echo_route());
194 let mut other = echo_route();
195 other.repository_id = "IDL:demo/Other:1.0".into();
196 m.add_route(other);
197 assert_eq!(m.all_routes().len(), 2);
198 }
199
200 #[test]
201 fn direction_variants_distinct() {
202 assert_ne!(Direction::CorbaToDds, Direction::DdsToCorba);
203 assert_ne!(Direction::CorbaToDds, Direction::Bidirectional);
204 }
205}