Skip to main content

zerodds_dcps/
qos.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! DCPS QoS — complete 22-policy sets for DataWriter/DataReader/Topic/
4//! Publisher/Subscriber/DomainParticipant per DDS 1.4 §2.2.3.
5//!
6//! Re-exports the policy data types from the `zerodds_qos` crate; the
7//! aggregates defined here are the DCPS-API view (what DataReader/Writer
8//! hold internally and what the runtime path accesses).
9
10pub use zerodds_qos::{
11    DeadlineQosPolicy, DestinationOrderKind, DestinationOrderQosPolicy, DurabilityKind,
12    DurabilityQosPolicy, DurabilityServiceQosPolicy, EntityFactoryQosPolicy, GroupDataQosPolicy,
13    HistoryKind, HistoryQosPolicy, LatencyBudgetQosPolicy, LifespanQosPolicy, LivelinessKind,
14    LivelinessQosPolicy, OwnershipKind, OwnershipQosPolicy, OwnershipStrengthQosPolicy,
15    PartitionQosPolicy, PresentationAccessScope, PresentationQosPolicy, PropertyQosPolicy,
16    ReaderDataLifecycleQosPolicy, ReliabilityKind, ReliabilityQosPolicy, ResourceLimitsQosPolicy,
17    TimeBasedFilterQosPolicy, TopicDataQosPolicy, TransportPriorityQosPolicy, UserDataQosPolicy,
18    WriterDataLifecycleQosPolicy,
19};
20
21use zerodds_qos::Duration;
22
23/// QoS set for a `DataWriter` — Spec §2.2.2.4.2 (all policies settable
24/// on the DataWriter).
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct DataWriterQos {
27    /// Reliability — default Reliable.
28    pub reliability: ReliabilityQosPolicy,
29    /// Durability — default Volatile.
30    pub durability: DurabilityQosPolicy,
31    /// Configures the persistence service (Spec §2.2.3.5).
32    pub durability_service: DurabilityServiceQosPolicy,
33    /// Deadline — default INFINITE.
34    pub deadline: DeadlineQosPolicy,
35    /// LatencyBudget — hint, no match effect (Spec §2.2.3.10).
36    pub latency_budget: LatencyBudgetQosPolicy,
37    /// Liveliness — default Automatic / INFINITE.
38    pub liveliness: LivelinessQosPolicy,
39    /// DestinationOrder — default ByReceptionTimestamp.
40    pub destination_order: DestinationOrderQosPolicy,
41    /// Lifespan — default INFINITE.
42    pub lifespan: LifespanQosPolicy,
43    /// Ownership — default Shared.
44    pub ownership: OwnershipQosPolicy,
45    /// Ownership strength — only with Exclusive.
46    pub ownership_strength: OwnershipStrengthQosPolicy,
47    /// Partition — default empty (matches only the ""-default partition).
48    pub partition: PartitionQosPolicy,
49    /// Presentation — default Instance/false/false.
50    pub presentation: PresentationQosPolicy,
51    /// History — default KeepLast(1).
52    pub history: HistoryQosPolicy,
53    /// Resource limits.
54    pub resource_limits: ResourceLimitsQosPolicy,
55    /// TransportPriority — hint, no match effect (Spec §2.2.3.15).
56    pub transport_priority: TransportPriorityQosPolicy,
57    /// WriterDataLifecycle — autodispose_unregistered_instances.
58    pub writer_data_lifecycle: WriterDataLifecycleQosPolicy,
59    /// UserData — opaque `sequence<octet>`, propagated via discovery.
60    pub user_data: UserDataQosPolicy,
61    /// TopicData — opaque `sequence<octet>`, propagated via discovery.
62    pub topic_data: TopicDataQosPolicy,
63    /// GroupData — opaque `sequence<octet>`, propagated via discovery.
64    pub group_data: GroupDataQosPolicy,
65    /// DataRepresentation (XTypes 1.3 §7.6.3.1.2): the offered
66    /// representation list (`XCDR=0`, `XCDR2=2`). `None` = runtime default
67    /// (`ZERODDS_DATA_REPR_OFFER` / `DEFAULT_OFFER`). Per-writer override
68    /// for targeted cross-vendor interop (e.g. `[XCDR1, XCDR2]` for
69    /// XCDR1 readers of ROS/RTI shapes) without a global default change.
70    pub data_representation: Option<alloc::vec::Vec<i16>>,
71}
72
73impl Default for DataWriterQos {
74    fn default() -> Self {
75        Self {
76            reliability: ReliabilityQosPolicy {
77                kind: ReliabilityKind::Reliable,
78                max_blocking_time: Duration::from_millis(100_i32),
79            },
80            durability: DurabilityQosPolicy {
81                kind: DurabilityKind::Volatile,
82            },
83            durability_service: DurabilityServiceQosPolicy::default(),
84            deadline: DeadlineQosPolicy::default(),
85            latency_budget: LatencyBudgetQosPolicy::default(),
86            liveliness: LivelinessQosPolicy::default(),
87            destination_order: DestinationOrderQosPolicy::default(),
88            lifespan: LifespanQosPolicy::default(),
89            ownership: OwnershipQosPolicy::default(),
90            ownership_strength: OwnershipStrengthQosPolicy::default(),
91            partition: PartitionQosPolicy::default(),
92            presentation: PresentationQosPolicy::default(),
93            history: HistoryQosPolicy {
94                kind: HistoryKind::KeepLast,
95                depth: 1,
96            },
97            resource_limits: ResourceLimitsQosPolicy {
98                max_samples: 1000_i32,
99                max_instances: 10_i32,
100                max_samples_per_instance: 100_i32,
101            },
102            transport_priority: TransportPriorityQosPolicy::default(),
103            writer_data_lifecycle: WriterDataLifecycleQosPolicy::default(),
104            user_data: UserDataQosPolicy::default(),
105            topic_data: TopicDataQosPolicy::default(),
106            group_data: GroupDataQosPolicy::default(),
107            data_representation: None,
108        }
109    }
110}
111
112/// QoS set for a `DataReader` — Spec §2.2.2.5.2.
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub struct DataReaderQos {
115    /// Reliability — reader default BestEffort (Spec §2.2.3.14.3).
116    pub reliability: ReliabilityQosPolicy,
117    /// Durability — default Volatile.
118    pub durability: DurabilityQosPolicy,
119    /// Deadline — default INFINITE.
120    pub deadline: DeadlineQosPolicy,
121    /// LatencyBudget — hint, no match effect.
122    pub latency_budget: LatencyBudgetQosPolicy,
123    /// Liveliness — default Automatic / INFINITE.
124    pub liveliness: LivelinessQosPolicy,
125    /// DestinationOrder — default ByReceptionTimestamp.
126    pub destination_order: DestinationOrderQosPolicy,
127    /// Ownership — default Shared.
128    pub ownership: OwnershipQosPolicy,
129    /// Partition — default empty.
130    pub partition: PartitionQosPolicy,
131    /// Presentation.
132    pub presentation: PresentationQosPolicy,
133    /// History — default KeepLast(1).
134    pub history: HistoryQosPolicy,
135    /// Resource limits.
136    pub resource_limits: ResourceLimitsQosPolicy,
137    /// TimeBasedFilter — minimum_separation per instance.
138    pub time_based_filter: TimeBasedFilterQosPolicy,
139    /// ReaderDataLifecycle — autopurge delays.
140    pub reader_data_lifecycle: ReaderDataLifecycleQosPolicy,
141    /// UserData (propagated via discovery).
142    pub user_data: UserDataQosPolicy,
143    /// TopicData (propagated via discovery).
144    pub topic_data: TopicDataQosPolicy,
145    /// GroupData (propagated via discovery).
146    pub group_data: GroupDataQosPolicy,
147    /// DataRepresentation (XTypes 1.3 §7.6.3.1.2): the accepted
148    /// representation list (`XCDR=0`, `XCDR2=2`). `None` = runtime default.
149    /// Per-reader override so that a reader specifically matches XCDR1
150    /// writers (ROS/RTI shapes) (`[XCDR1, XCDR2]`) without a global default.
151    pub data_representation: Option<alloc::vec::Vec<i16>>,
152}
153
154impl Default for DataReaderQos {
155    fn default() -> Self {
156        Self {
157            reliability: ReliabilityQosPolicy {
158                kind: ReliabilityKind::BestEffort,
159                max_blocking_time: Duration::from_millis(100_i32),
160            },
161            durability: DurabilityQosPolicy {
162                kind: DurabilityKind::Volatile,
163            },
164            deadline: DeadlineQosPolicy::default(),
165            latency_budget: LatencyBudgetQosPolicy::default(),
166            liveliness: LivelinessQosPolicy::default(),
167            destination_order: DestinationOrderQosPolicy::default(),
168            ownership: OwnershipQosPolicy::default(),
169            partition: PartitionQosPolicy::default(),
170            presentation: PresentationQosPolicy::default(),
171            history: HistoryQosPolicy {
172                kind: HistoryKind::KeepLast,
173                depth: 1,
174            },
175            resource_limits: ResourceLimitsQosPolicy {
176                max_samples: 1000_i32,
177                max_instances: 10_i32,
178                max_samples_per_instance: 100_i32,
179            },
180            time_based_filter: TimeBasedFilterQosPolicy::default(),
181            reader_data_lifecycle: ReaderDataLifecycleQosPolicy::default(),
182            user_data: UserDataQosPolicy::default(),
183            topic_data: TopicDataQosPolicy::default(),
184            group_data: GroupDataQosPolicy::default(),
185            data_representation: None,
186        }
187    }
188}
189
190/// QoS set for a `Topic` — Spec §2.2.2.3.2.
191#[derive(Debug, Clone, PartialEq, Eq, Default)]
192pub struct TopicQos {
193    /// Default durability of the topic.
194    pub durability: DurabilityQosPolicy,
195    /// DurabilityService default of the topic.
196    pub durability_service: DurabilityServiceQosPolicy,
197    /// Default deadline.
198    pub deadline: DeadlineQosPolicy,
199    /// Default LatencyBudget.
200    pub latency_budget: LatencyBudgetQosPolicy,
201    /// Default liveliness.
202    pub liveliness: LivelinessQosPolicy,
203    /// Default reliability.
204    pub reliability: ReliabilityQosPolicy,
205    /// Default DestinationOrder.
206    pub destination_order: DestinationOrderQosPolicy,
207    /// Default history.
208    pub history: HistoryQosPolicy,
209    /// Default resource limits.
210    pub resource_limits: ResourceLimitsQosPolicy,
211    /// Default TransportPriority.
212    pub transport_priority: TransportPriorityQosPolicy,
213    /// Default lifespan.
214    pub lifespan: LifespanQosPolicy,
215    /// Default ownership.
216    pub ownership: OwnershipQosPolicy,
217    /// TopicData (propagated via discovery).
218    pub topic_data: TopicDataQosPolicy,
219}
220
221/// QoS set for the `DomainParticipant` — Spec §2.2.2.2.2.
222#[derive(Debug, Clone, PartialEq, Eq, Default)]
223pub struct DomainParticipantQos {
224    /// UserData (propagated via discovery).
225    pub user_data: UserDataQosPolicy,
226    /// EntityFactory — auto-enable of child entities.
227    pub entity_factory: EntityFactoryQosPolicy,
228    /// Property — name/value configuration carried on the participant
229    /// (DDS-Security `dds.sec.*` plugin config, incl. the security logger).
230    pub property: PropertyQosPolicy,
231}
232
233/// QoS set for the `Publisher` — Spec §2.2.2.4.1.
234#[derive(Debug, Clone, PartialEq, Eq, Default)]
235pub struct PublisherQos {
236    /// Presentation — coherent/ordered access.
237    pub presentation: PresentationQosPolicy,
238    /// Partition — default empty.
239    pub partition: PartitionQosPolicy,
240    /// GroupData (propagated via discovery).
241    pub group_data: GroupDataQosPolicy,
242    /// EntityFactory — auto-enable of DataWriters.
243    pub entity_factory: EntityFactoryQosPolicy,
244}
245
246/// QoS set for the `Subscriber` — Spec §2.2.2.5.1.
247#[derive(Debug, Clone, PartialEq, Eq, Default)]
248pub struct SubscriberQos {
249    /// Presentation — coherent/ordered access.
250    pub presentation: PresentationQosPolicy,
251    /// Partition — default empty.
252    pub partition: PartitionQosPolicy,
253    /// GroupData (propagated via discovery).
254    pub group_data: GroupDataQosPolicy,
255    /// EntityFactory — auto-enable of DataReaders.
256    pub entity_factory: EntityFactoryQosPolicy,
257}
258
259/// Materializes a DDS-XML-resolved [`zerodds_qos::WriterQos`] (e.g. from
260/// `zerodds_xml::QosProfileRegistry::writer_qos`) into the DCPS `DataWriterQos`.
261/// All shared policies carry over; DCPS-only policies not expressible in the
262/// qos-aggregate (`data_representation`) keep their default. Closes the
263/// DDS-XML-1.0 QoS-profile → entity-creation path.
264impl From<zerodds_qos::WriterQos> for DataWriterQos {
265    fn from(w: zerodds_qos::WriterQos) -> Self {
266        Self {
267            durability: w.durability,
268            durability_service: w.durability_service,
269            deadline: w.deadline,
270            latency_budget: w.latency_budget,
271            liveliness: w.liveliness,
272            reliability: w.reliability,
273            destination_order: w.destination_order,
274            history: w.history,
275            resource_limits: w.resource_limits,
276            transport_priority: w.transport_priority,
277            lifespan: w.lifespan,
278            ownership: w.ownership,
279            ownership_strength: w.ownership_strength,
280            presentation: w.presentation,
281            partition: w.partition,
282            writer_data_lifecycle: w.writer_data_lifecycle,
283            user_data: w.user_data,
284            topic_data: w.topic_data,
285            group_data: w.group_data,
286            ..Self::default()
287        }
288    }
289}
290
291/// Materializes a DDS-XML-resolved [`zerodds_qos::ReaderQos`] into the DCPS
292/// `DataReaderQos`. See [`From<zerodds_qos::WriterQos>`] for the writer side.
293impl From<zerodds_qos::ReaderQos> for DataReaderQos {
294    fn from(r: zerodds_qos::ReaderQos) -> Self {
295        Self {
296            durability: r.durability,
297            deadline: r.deadline,
298            latency_budget: r.latency_budget,
299            liveliness: r.liveliness,
300            reliability: r.reliability,
301            destination_order: r.destination_order,
302            history: r.history,
303            resource_limits: r.resource_limits,
304            ownership: r.ownership,
305            time_based_filter: r.time_based_filter,
306            presentation: r.presentation,
307            partition: r.partition,
308            reader_data_lifecycle: r.reader_data_lifecycle,
309            user_data: r.user_data,
310            topic_data: r.topic_data,
311            group_data: r.group_data,
312            ..Self::default()
313        }
314    }
315}
316
317#[cfg(test)]
318mod data_representation_tests {
319    use super::{DataReaderQos, DataWriterQos};
320
321    #[test]
322    fn data_representation_defaults_none_and_settable() {
323        // B5: per-endpoint DataRepresentation override (XTypes §7.6.3.1.2).
324        // Default None = runtime default; settable for a targeted XCDR1 offer.
325        assert_eq!(DataWriterQos::default().data_representation, None);
326        assert_eq!(DataReaderQos::default().data_representation, None);
327        let r = DataReaderQos {
328            data_representation: Some(alloc::vec![0_i16, 2]), // [XCDR1, XCDR2]
329            ..Default::default()
330        };
331        assert_eq!(r.data_representation.as_deref(), Some(&[0_i16, 2][..]));
332        let w = DataWriterQos {
333            data_representation: Some(alloc::vec![0_i16]), // XCDR1-only
334            ..Default::default()
335        };
336        assert_eq!(w.data_representation.as_deref(), Some(&[0_i16][..]));
337    }
338
339    #[test]
340    fn from_qos_aggregate_carries_policies() {
341        use zerodds_qos::{HistoryKind, ReliabilityKind};
342        let mut w = zerodds_qos::WriterQos::default();
343        w.history.kind = HistoryKind::KeepLast;
344        w.history.depth = 42;
345        w.reliability.kind = ReliabilityKind::Reliable;
346        let dw: DataWriterQos = w.into();
347        assert_eq!(dw.history.depth, 42);
348        assert_eq!(dw.reliability.kind, ReliabilityKind::Reliable);
349        assert_eq!(dw.data_representation, None); // DCPS-only → default
350
351        let mut rq = zerodds_qos::ReaderQos::default();
352        rq.history.depth = 7;
353        let dr: DataReaderQos = rq.into();
354        assert_eq!(dr.history.depth, 7);
355        assert_eq!(dr.data_representation, None);
356    }
357}