1use crate::publication_data::PublicationBuiltinTopicData;
10use crate::subscription_data::SubscriptionBuiltinTopicData;
11
12use zerodds_qos::{DurabilityQosPolicy, ReaderQos, WriterQos};
13
14impl PublicationBuiltinTopicData {
32 #[must_use]
40 pub fn as_writer_qos(&self) -> WriterQos {
41 WriterQos {
42 durability: DurabilityQosPolicy {
43 kind: self.durability,
44 },
45 reliability: self.reliability,
46 ..WriterQos::default()
47 }
48 }
49
50 #[must_use]
54 pub fn with_writer_qos(mut self, qos: &WriterQos) -> Self {
55 self.durability = qos.durability.kind;
56 self.reliability = qos.reliability;
57 self
58 }
59}
60
61impl SubscriptionBuiltinTopicData {
62 #[must_use]
67 pub fn as_reader_qos(&self) -> ReaderQos {
68 ReaderQos {
69 durability: DurabilityQosPolicy {
70 kind: self.durability,
71 },
72 reliability: self.reliability,
73 ..ReaderQos::default()
74 }
75 }
76
77 #[must_use]
79 pub fn with_reader_qos(mut self, qos: &ReaderQos) -> Self {
80 self.durability = qos.durability.kind;
81 self.reliability = qos.reliability;
82 self
83 }
84}
85
86#[cfg(test)]
87#[allow(clippy::unwrap_used, clippy::unreachable, clippy::panic)]
88mod tests {
89 use super::*;
90 use crate::publication_data::{DurabilityKind, ReliabilityKind, ReliabilityQos};
91 use crate::wire_types::{EntityId, Guid, GuidPrefix};
92 use zerodds_qos::Duration;
93
94 #[test]
95 fn durability_kind_is_reexport_not_duplicate() {
96 fn assert_same_type<T>(_a: &T, _b: &T) {}
99 let rtps = DurabilityKind::Transient;
100 let qos = zerodds_qos::DurabilityKind::Transient;
101 assert_same_type(&rtps, &qos);
102 assert_eq!(rtps, qos);
103 }
104
105 #[test]
106 fn reliability_kind_is_reexport_not_duplicate() {
107 let rtps = ReliabilityKind::Reliable;
108 let qos = zerodds_qos::ReliabilityKind::Reliable;
109 assert_eq!(rtps, qos);
110 }
111
112 #[test]
113 fn duration_is_reexport_not_duplicate() {
114 let d = Duration::from_secs(7);
115 let qd = zerodds_qos::Duration::from_secs(7);
116 assert_eq!(d, qd);
117 }
118
119 #[test]
120 fn writer_reader_qos_match_by_defaults() {
121 let pub_data = PublicationBuiltinTopicData {
122 key: Guid::new(
123 GuidPrefix::from_bytes([1; 12]),
124 EntityId::user_writer_with_key([0, 0, 1]),
125 ),
126 participant_key: Guid::new(GuidPrefix::from_bytes([1; 12]), EntityId::PARTICIPANT),
127 topic_name: alloc::string::String::from("T"),
128 type_name: alloc::string::String::from("X"),
129 durability: DurabilityKind::TransientLocal,
130 reliability: ReliabilityQos {
131 kind: ReliabilityKind::Reliable,
132 max_blocking_time: Duration {
133 seconds: 0,
134 fraction: 0,
135 },
136 },
137 ownership: zerodds_qos::OwnershipKind::Shared,
138 ownership_strength: 0,
139 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
140 deadline: zerodds_qos::DeadlineQosPolicy::default(),
141 lifespan: zerodds_qos::LifespanQosPolicy::default(),
142 partition: alloc::vec::Vec::new(),
143 user_data: alloc::vec::Vec::new(),
144 topic_data: alloc::vec::Vec::new(),
145 group_data: alloc::vec::Vec::new(),
146 type_information: None,
147 data_representation: alloc::vec![2],
148 security_info: None,
149 service_instance_name: None,
150 related_entity_guid: None,
151 topic_aliases: None,
152 type_identifier: zerodds_types::TypeIdentifier::None,
153 unicast_locators: alloc::vec::Vec::new(),
154 multicast_locators: alloc::vec::Vec::new(),
155 };
156 let sub_data = SubscriptionBuiltinTopicData {
157 key: Guid::new(
158 GuidPrefix::from_bytes([2; 12]),
159 EntityId::user_reader_with_key([0, 0, 2]),
160 ),
161 participant_key: Guid::new(GuidPrefix::from_bytes([2; 12]), EntityId::PARTICIPANT),
162 topic_name: alloc::string::String::from("T"),
163 type_name: alloc::string::String::from("X"),
164 durability: DurabilityKind::Volatile,
165 reliability: ReliabilityQos {
166 kind: ReliabilityKind::BestEffort,
167 max_blocking_time: Duration {
168 seconds: 0,
169 fraction: 0,
170 },
171 },
172 ownership: zerodds_qos::OwnershipKind::Shared,
173 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
174 deadline: zerodds_qos::DeadlineQosPolicy::default(),
175 partition: alloc::vec::Vec::new(),
176 user_data: alloc::vec::Vec::new(),
177 topic_data: alloc::vec::Vec::new(),
178 group_data: alloc::vec::Vec::new(),
179 type_information: None,
180 data_representation: alloc::vec![2],
181 content_filter: None,
182 security_info: None,
183 service_instance_name: None,
184 related_entity_guid: None,
185 topic_aliases: None,
186 type_identifier: zerodds_types::TypeIdentifier::None,
187 unicast_locators: alloc::vec::Vec::new(),
188 multicast_locators: alloc::vec::Vec::new(),
189 };
190 let wq = pub_data.as_writer_qos();
191 let rq = sub_data.as_reader_qos();
192 assert!(zerodds_qos::check_compatibility(&wq, &rq).is_compatible());
193 }
194
195 #[test]
201 fn besteffort_writer_reliable_reader_is_incompatible_via_bridge() {
202 let pub_data = PublicationBuiltinTopicData {
203 key: Guid::new(
204 GuidPrefix::from_bytes([1; 12]),
205 EntityId::user_writer_with_key([0, 0, 1]),
206 ),
207 participant_key: Guid::new(GuidPrefix::from_bytes([1; 12]), EntityId::PARTICIPANT),
208 topic_name: alloc::string::String::from("T"),
209 type_name: alloc::string::String::from("X"),
210 durability: DurabilityKind::Volatile,
211 reliability: ReliabilityQos {
212 kind: ReliabilityKind::BestEffort,
213 max_blocking_time: Duration {
214 seconds: 0,
215 fraction: 0,
216 },
217 },
218 ownership: zerodds_qos::OwnershipKind::Shared,
219 ownership_strength: 0,
220 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
221 deadline: zerodds_qos::DeadlineQosPolicy::default(),
222 lifespan: zerodds_qos::LifespanQosPolicy::default(),
223 partition: alloc::vec::Vec::new(),
224 user_data: alloc::vec::Vec::new(),
225 topic_data: alloc::vec::Vec::new(),
226 group_data: alloc::vec::Vec::new(),
227 type_information: None,
228 data_representation: alloc::vec![2],
229 security_info: None,
230 service_instance_name: None,
231 related_entity_guid: None,
232 topic_aliases: None,
233 type_identifier: zerodds_types::TypeIdentifier::None,
234 unicast_locators: alloc::vec::Vec::new(),
235 multicast_locators: alloc::vec::Vec::new(),
236 };
237 let sub_data = SubscriptionBuiltinTopicData {
238 key: Guid::new(
239 GuidPrefix::from_bytes([2; 12]),
240 EntityId::user_reader_with_key([0, 0, 2]),
241 ),
242 participant_key: Guid::new(GuidPrefix::from_bytes([2; 12]), EntityId::PARTICIPANT),
243 topic_name: alloc::string::String::from("T"),
244 type_name: alloc::string::String::from("X"),
245 durability: DurabilityKind::Volatile,
246 reliability: ReliabilityQos {
247 kind: ReliabilityKind::Reliable,
248 max_blocking_time: Duration {
249 seconds: 0,
250 fraction: 0,
251 },
252 },
253 ownership: zerodds_qos::OwnershipKind::Shared,
254 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
255 deadline: zerodds_qos::DeadlineQosPolicy::default(),
256 partition: alloc::vec::Vec::new(),
257 user_data: alloc::vec::Vec::new(),
258 topic_data: alloc::vec::Vec::new(),
259 group_data: alloc::vec::Vec::new(),
260 type_information: None,
261 data_representation: alloc::vec![2],
262 content_filter: None,
263 security_info: None,
264 service_instance_name: None,
265 related_entity_guid: None,
266 topic_aliases: None,
267 type_identifier: zerodds_types::TypeIdentifier::None,
268 unicast_locators: alloc::vec::Vec::new(),
269 multicast_locators: alloc::vec::Vec::new(),
270 };
271 let wq = pub_data.as_writer_qos();
272 let rq = sub_data.as_reader_qos();
273 let res = zerodds_qos::check_compatibility(&wq, &rq);
274 assert!(!res.is_compatible());
275 match res {
276 zerodds_qos::CompatibilityResult::Incompatible(reasons) => {
277 assert!(
278 reasons.contains(&zerodds_qos::IncompatibleReason::Reliability),
279 "expected Reliability reason, got {reasons:?}"
280 );
281 }
282 zerodds_qos::CompatibilityResult::Compatible => {
283 unreachable!("BestEffort writer vs Reliable reader must not match")
284 }
285 }
286 }
287
288 #[test]
291 fn volatile_writer_transient_local_reader_incompatible_via_bridge() {
292 let pub_data = PublicationBuiltinTopicData {
293 key: Guid::new(
294 GuidPrefix::from_bytes([1; 12]),
295 EntityId::user_writer_with_key([0, 0, 1]),
296 ),
297 participant_key: Guid::new(GuidPrefix::from_bytes([1; 12]), EntityId::PARTICIPANT),
298 topic_name: alloc::string::String::from("T"),
299 type_name: alloc::string::String::from("X"),
300 durability: DurabilityKind::Volatile,
301 reliability: ReliabilityQos {
302 kind: ReliabilityKind::Reliable,
303 max_blocking_time: Duration {
304 seconds: 0,
305 fraction: 0,
306 },
307 },
308 ownership: zerodds_qos::OwnershipKind::Shared,
309 ownership_strength: 0,
310 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
311 deadline: zerodds_qos::DeadlineQosPolicy::default(),
312 lifespan: zerodds_qos::LifespanQosPolicy::default(),
313 partition: alloc::vec::Vec::new(),
314 user_data: alloc::vec::Vec::new(),
315 topic_data: alloc::vec::Vec::new(),
316 group_data: alloc::vec::Vec::new(),
317 type_information: None,
318 data_representation: alloc::vec![2],
319 security_info: None,
320 service_instance_name: None,
321 related_entity_guid: None,
322 topic_aliases: None,
323 type_identifier: zerodds_types::TypeIdentifier::None,
324 unicast_locators: alloc::vec::Vec::new(),
325 multicast_locators: alloc::vec::Vec::new(),
326 };
327 let sub_data = SubscriptionBuiltinTopicData {
328 key: Guid::new(
329 GuidPrefix::from_bytes([2; 12]),
330 EntityId::user_reader_with_key([0, 0, 2]),
331 ),
332 participant_key: Guid::new(GuidPrefix::from_bytes([2; 12]), EntityId::PARTICIPANT),
333 topic_name: alloc::string::String::from("T"),
334 type_name: alloc::string::String::from("X"),
335 durability: DurabilityKind::TransientLocal,
336 reliability: ReliabilityQos {
337 kind: ReliabilityKind::BestEffort,
338 max_blocking_time: Duration {
339 seconds: 0,
340 fraction: 0,
341 },
342 },
343 ownership: zerodds_qos::OwnershipKind::Shared,
344 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
345 deadline: zerodds_qos::DeadlineQosPolicy::default(),
346 partition: alloc::vec::Vec::new(),
347 user_data: alloc::vec::Vec::new(),
348 topic_data: alloc::vec::Vec::new(),
349 group_data: alloc::vec::Vec::new(),
350 type_information: None,
351 data_representation: alloc::vec![2],
352 content_filter: None,
353 security_info: None,
354 service_instance_name: None,
355 related_entity_guid: None,
356 topic_aliases: None,
357 type_identifier: zerodds_types::TypeIdentifier::None,
358 unicast_locators: alloc::vec::Vec::new(),
359 multicast_locators: alloc::vec::Vec::new(),
360 };
361 let wq = pub_data.as_writer_qos();
362 let rq = sub_data.as_reader_qos();
363 let res = zerodds_qos::check_compatibility(&wq, &rq);
364 assert!(!res.is_compatible());
365 }
366}