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 };
154 let sub_data = SubscriptionBuiltinTopicData {
155 key: Guid::new(
156 GuidPrefix::from_bytes([2; 12]),
157 EntityId::user_reader_with_key([0, 0, 2]),
158 ),
159 participant_key: Guid::new(GuidPrefix::from_bytes([2; 12]), EntityId::PARTICIPANT),
160 topic_name: alloc::string::String::from("T"),
161 type_name: alloc::string::String::from("X"),
162 durability: DurabilityKind::Volatile,
163 reliability: ReliabilityQos {
164 kind: ReliabilityKind::BestEffort,
165 max_blocking_time: Duration {
166 seconds: 0,
167 fraction: 0,
168 },
169 },
170 ownership: zerodds_qos::OwnershipKind::Shared,
171 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
172 deadline: zerodds_qos::DeadlineQosPolicy::default(),
173 partition: alloc::vec::Vec::new(),
174 user_data: alloc::vec::Vec::new(),
175 topic_data: alloc::vec::Vec::new(),
176 group_data: alloc::vec::Vec::new(),
177 type_information: None,
178 data_representation: alloc::vec![2],
179 content_filter: None,
180 security_info: None,
181 service_instance_name: None,
182 related_entity_guid: None,
183 topic_aliases: None,
184 type_identifier: zerodds_types::TypeIdentifier::None,
185 };
186 let wq = pub_data.as_writer_qos();
187 let rq = sub_data.as_reader_qos();
188 assert!(zerodds_qos::check_compatibility(&wq, &rq).is_compatible());
189 }
190
191 #[test]
197 fn besteffort_writer_reliable_reader_is_incompatible_via_bridge() {
198 let pub_data = PublicationBuiltinTopicData {
199 key: Guid::new(
200 GuidPrefix::from_bytes([1; 12]),
201 EntityId::user_writer_with_key([0, 0, 1]),
202 ),
203 participant_key: Guid::new(GuidPrefix::from_bytes([1; 12]), EntityId::PARTICIPANT),
204 topic_name: alloc::string::String::from("T"),
205 type_name: alloc::string::String::from("X"),
206 durability: DurabilityKind::Volatile,
207 reliability: ReliabilityQos {
208 kind: ReliabilityKind::BestEffort,
209 max_blocking_time: Duration {
210 seconds: 0,
211 fraction: 0,
212 },
213 },
214 ownership: zerodds_qos::OwnershipKind::Shared,
215 ownership_strength: 0,
216 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
217 deadline: zerodds_qos::DeadlineQosPolicy::default(),
218 lifespan: zerodds_qos::LifespanQosPolicy::default(),
219 partition: alloc::vec::Vec::new(),
220 user_data: alloc::vec::Vec::new(),
221 topic_data: alloc::vec::Vec::new(),
222 group_data: alloc::vec::Vec::new(),
223 type_information: None,
224 data_representation: alloc::vec![2],
225 security_info: None,
226 service_instance_name: None,
227 related_entity_guid: None,
228 topic_aliases: None,
229 type_identifier: zerodds_types::TypeIdentifier::None,
230 };
231 let sub_data = SubscriptionBuiltinTopicData {
232 key: Guid::new(
233 GuidPrefix::from_bytes([2; 12]),
234 EntityId::user_reader_with_key([0, 0, 2]),
235 ),
236 participant_key: Guid::new(GuidPrefix::from_bytes([2; 12]), EntityId::PARTICIPANT),
237 topic_name: alloc::string::String::from("T"),
238 type_name: alloc::string::String::from("X"),
239 durability: DurabilityKind::Volatile,
240 reliability: ReliabilityQos {
241 kind: ReliabilityKind::Reliable,
242 max_blocking_time: Duration {
243 seconds: 0,
244 fraction: 0,
245 },
246 },
247 ownership: zerodds_qos::OwnershipKind::Shared,
248 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
249 deadline: zerodds_qos::DeadlineQosPolicy::default(),
250 partition: alloc::vec::Vec::new(),
251 user_data: alloc::vec::Vec::new(),
252 topic_data: alloc::vec::Vec::new(),
253 group_data: alloc::vec::Vec::new(),
254 type_information: None,
255 data_representation: alloc::vec![2],
256 content_filter: None,
257 security_info: None,
258 service_instance_name: None,
259 related_entity_guid: None,
260 topic_aliases: None,
261 type_identifier: zerodds_types::TypeIdentifier::None,
262 };
263 let wq = pub_data.as_writer_qos();
264 let rq = sub_data.as_reader_qos();
265 let res = zerodds_qos::check_compatibility(&wq, &rq);
266 assert!(!res.is_compatible());
267 match res {
268 zerodds_qos::CompatibilityResult::Incompatible(reasons) => {
269 assert!(
270 reasons.contains(&zerodds_qos::IncompatibleReason::Reliability),
271 "expected Reliability reason, got {reasons:?}"
272 );
273 }
274 zerodds_qos::CompatibilityResult::Compatible => {
275 unreachable!("BestEffort writer vs Reliable reader must not match")
276 }
277 }
278 }
279
280 #[test]
283 fn volatile_writer_transient_local_reader_incompatible_via_bridge() {
284 let pub_data = PublicationBuiltinTopicData {
285 key: Guid::new(
286 GuidPrefix::from_bytes([1; 12]),
287 EntityId::user_writer_with_key([0, 0, 1]),
288 ),
289 participant_key: Guid::new(GuidPrefix::from_bytes([1; 12]), EntityId::PARTICIPANT),
290 topic_name: alloc::string::String::from("T"),
291 type_name: alloc::string::String::from("X"),
292 durability: DurabilityKind::Volatile,
293 reliability: ReliabilityQos {
294 kind: ReliabilityKind::Reliable,
295 max_blocking_time: Duration {
296 seconds: 0,
297 fraction: 0,
298 },
299 },
300 ownership: zerodds_qos::OwnershipKind::Shared,
301 ownership_strength: 0,
302 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
303 deadline: zerodds_qos::DeadlineQosPolicy::default(),
304 lifespan: zerodds_qos::LifespanQosPolicy::default(),
305 partition: alloc::vec::Vec::new(),
306 user_data: alloc::vec::Vec::new(),
307 topic_data: alloc::vec::Vec::new(),
308 group_data: alloc::vec::Vec::new(),
309 type_information: None,
310 data_representation: alloc::vec![2],
311 security_info: None,
312 service_instance_name: None,
313 related_entity_guid: None,
314 topic_aliases: None,
315 type_identifier: zerodds_types::TypeIdentifier::None,
316 };
317 let sub_data = SubscriptionBuiltinTopicData {
318 key: Guid::new(
319 GuidPrefix::from_bytes([2; 12]),
320 EntityId::user_reader_with_key([0, 0, 2]),
321 ),
322 participant_key: Guid::new(GuidPrefix::from_bytes([2; 12]), EntityId::PARTICIPANT),
323 topic_name: alloc::string::String::from("T"),
324 type_name: alloc::string::String::from("X"),
325 durability: DurabilityKind::TransientLocal,
326 reliability: ReliabilityQos {
327 kind: ReliabilityKind::BestEffort,
328 max_blocking_time: Duration {
329 seconds: 0,
330 fraction: 0,
331 },
332 },
333 ownership: zerodds_qos::OwnershipKind::Shared,
334 liveliness: zerodds_qos::LivelinessQosPolicy::default(),
335 deadline: zerodds_qos::DeadlineQosPolicy::default(),
336 partition: alloc::vec::Vec::new(),
337 user_data: alloc::vec::Vec::new(),
338 topic_data: alloc::vec::Vec::new(),
339 group_data: alloc::vec::Vec::new(),
340 type_information: None,
341 data_representation: alloc::vec![2],
342 content_filter: None,
343 security_info: None,
344 service_instance_name: None,
345 related_entity_guid: None,
346 topic_aliases: None,
347 type_identifier: zerodds_types::TypeIdentifier::None,
348 };
349 let wq = pub_data.as_writer_qos();
350 let rq = sub_data.as_reader_qos();
351 let res = zerodds_qos::check_compatibility(&wq, &rq);
352 assert!(!res.is_compatible());
353 }
354}