Skip to main content

zerodds_ast/node/
deployment.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! Deployment nodes. Spec §3.7.
4//!
5//! A QoS profile holds typed policy values, not XML text. Every field a
6//! DDS-XML document can leave unset is `Option`, so "not written" stays
7//! distinguishable from "written as the default" — a distinction a
8//! profile that inherits from another one depends on.
9
10use crate::facet::Facets;
11use crate::node::AnyId;
12use crate::node::type_::TypeNode;
13use alloc::string::String;
14use alloc::vec::Vec;
15use zerodds_ast_core::{Id, NodeId, Ref};
16
17/// A deployment library: the container DDS-XML declares profiles,
18/// domains and participants in. Spec §3.7.
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct LibraryNode {
21    /// Stable identity.
22    pub node_id: NodeId,
23    /// Library name.
24    pub name: String,
25    /// Everything declared inside, in declaration order.
26    pub children: Vec<AnyId>,
27    /// Per-source information. Spec §4.
28    pub facets: Facets,
29}
30
31/// A DDS domain. Spec §3.7.
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct DomainNode {
34    /// Stable identity.
35    pub node_id: NodeId,
36    /// Domain name.
37    pub name: String,
38    /// Numeric domain id.
39    pub domain_id: u32,
40    /// Topics declared in this domain.
41    pub topics: Vec<Id<TopicNode>>,
42    /// Enclosing library.
43    pub parent: Id<LibraryNode>,
44    /// Per-source information. Spec §4.
45    pub facets: Facets,
46}
47
48/// A topic. Spec §3.7.
49#[derive(Debug, Clone, PartialEq, Eq)]
50pub struct TopicNode {
51    /// Stable identity.
52    pub node_id: NodeId,
53    /// Topic name as it appears on the wire.
54    pub name: String,
55    /// The type published on it.
56    pub type_: Ref<TypeNode>,
57    /// QoS profile, if one is bound.
58    pub qos: Option<Ref<QosProfileNode>>,
59    /// Enclosing domain.
60    pub parent: Id<DomainNode>,
61    /// Per-source information. Spec §4.
62    pub facets: Facets,
63}
64
65/// A QoS profile. Spec §3.7.
66#[derive(Debug, Clone, PartialEq, Eq)]
67pub struct QosProfileNode {
68    /// Stable identity.
69    pub node_id: NodeId,
70    /// Profile name.
71    pub name: String,
72    /// Profile this one inherits from.
73    pub base: Option<Ref<QosProfileNode>>,
74    /// Policy values, in declaration order.
75    pub policies: Vec<QosPolicy>,
76    /// Enclosing library.
77    pub parent: Id<LibraryNode>,
78    /// Per-source information. Spec §4.
79    pub facets: Facets,
80}
81
82/// A domain participant. Spec §3.7.
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct ParticipantNode {
85    /// Stable identity.
86    pub node_id: NodeId,
87    /// Participant name.
88    pub name: String,
89    /// Domain it joins.
90    pub domain: Ref<DomainNode>,
91    /// QoS profile, if one is bound.
92    pub qos: Option<Ref<QosProfileNode>>,
93    /// Endpoints it owns.
94    pub endpoints: Vec<Id<EndpointNode>>,
95    /// Enclosing library.
96    pub parent: Id<LibraryNode>,
97    /// Per-source information. Spec §4.
98    pub facets: Facets,
99}
100
101/// Whether an endpoint publishes or subscribes.
102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
103pub enum EndpointRole {
104    /// Publishing side.
105    DataWriter,
106    /// Subscribing side.
107    DataReader,
108}
109
110impl EndpointRole {
111    /// Both roles.
112    pub const ALL: [Self; 2] = [Self::DataWriter, Self::DataReader];
113}
114
115/// A reader or writer endpoint. Spec §3.7.
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct EndpointNode {
118    /// Stable identity.
119    pub node_id: NodeId,
120    /// Endpoint name.
121    pub name: String,
122    /// Which side.
123    pub role: EndpointRole,
124    /// Topic it is bound to.
125    pub topic: Ref<TopicNode>,
126    /// QoS profile, if one is bound.
127    pub qos: Option<Ref<QosProfileNode>>,
128    /// Owning participant.
129    pub parent: Id<ParticipantNode>,
130    /// Per-source information. Spec §4.
131    pub facets: Facets,
132}
133
134/// A duration, as DDS-DCPS 1.4 §2.2.1.1 defines it.
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
136pub struct Duration {
137    /// Whole seconds.
138    pub sec: i32,
139    /// Additional nanoseconds.
140    pub nanosec: u32,
141}
142
143impl Duration {
144    /// `DURATION_INFINITE`, DDS-DCPS 1.4 §2.2.3.
145    pub const INFINITE: Self = Self {
146        sec: 0x7fff_ffff,
147        nanosec: 0xffff_ffff,
148    };
149
150    /// Zero duration.
151    pub const ZERO: Self = Self { sec: 0, nanosec: 0 };
152}
153
154/// Which policy a [`QosPolicy`] carries.
155///
156/// Kept separate from the payload so a test can assert the set is
157/// complete against DDS-DCPS 1.4 §2.2.3 without constructing payloads.
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
159pub enum QosPolicyKind {
160    /// §2.2.3.4
161    UserData,
162    /// §2.2.3.5
163    TopicData,
164    /// §2.2.3.6
165    GroupData,
166    /// §2.2.3.7
167    Durability,
168    /// §2.2.3.8
169    DurabilityService,
170    /// §2.2.3.9
171    Presentation,
172    /// §2.2.3.10
173    Deadline,
174    /// §2.2.3.11
175    LatencyBudget,
176    /// §2.2.3.12
177    Ownership,
178    /// §2.2.3.13
179    OwnershipStrength,
180    /// §2.2.3.14
181    Liveliness,
182    /// §2.2.3.15
183    TimeBasedFilter,
184    /// §2.2.3.16
185    Partition,
186    /// §2.2.3.17
187    Reliability,
188    /// §2.2.3.18
189    TransportPriority,
190    /// §2.2.3.19
191    Lifespan,
192    /// §2.2.3.20
193    DestinationOrder,
194    /// §2.2.3.21
195    History,
196    /// §2.2.3.22
197    ResourceLimits,
198    /// §2.2.3.23
199    EntityFactory,
200    /// §2.2.3.24
201    WriterDataLifecycle,
202    /// §2.2.3.25
203    ReaderDataLifecycle,
204    /// DDS-XTypes 1.3 §7.6.3
205    DataRepresentation,
206    /// DDS-XTypes 1.3 §7.6.4
207    TypeConsistencyEnforcement,
208}
209
210impl QosPolicyKind {
211    /// Every policy of DDS-DCPS 1.4 §2.2.3 plus the two XTypes 1.3 adds.
212    pub const ALL: [Self; 24] = [
213        Self::UserData,
214        Self::TopicData,
215        Self::GroupData,
216        Self::Durability,
217        Self::DurabilityService,
218        Self::Presentation,
219        Self::Deadline,
220        Self::LatencyBudget,
221        Self::Ownership,
222        Self::OwnershipStrength,
223        Self::Liveliness,
224        Self::TimeBasedFilter,
225        Self::Partition,
226        Self::Reliability,
227        Self::TransportPriority,
228        Self::Lifespan,
229        Self::DestinationOrder,
230        Self::History,
231        Self::ResourceLimits,
232        Self::EntityFactory,
233        Self::WriterDataLifecycle,
234        Self::ReaderDataLifecycle,
235        Self::DataRepresentation,
236        Self::TypeConsistencyEnforcement,
237    ];
238}
239
240/// `DurabilityQosPolicyKind`, DDS-DCPS 1.4 §2.2.3.7.
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242pub enum DurabilityKind {
243    /// `VOLATILE_DURABILITY_QOS`
244    Volatile,
245    /// `TRANSIENT_LOCAL_DURABILITY_QOS`
246    TransientLocal,
247    /// `TRANSIENT_DURABILITY_QOS`
248    Transient,
249    /// `PERSISTENT_DURABILITY_QOS`
250    Persistent,
251}
252
253/// `ReliabilityQosPolicyKind`, DDS-DCPS 1.4 §2.2.3.17.
254#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
255pub enum ReliabilityKind {
256    /// `BEST_EFFORT_RELIABILITY_QOS`
257    BestEffort,
258    /// `RELIABLE_RELIABILITY_QOS`
259    Reliable,
260}
261
262/// `HistoryQosPolicyKind`, DDS-DCPS 1.4 §2.2.3.21.
263#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
264pub enum HistoryKind {
265    /// `KEEP_LAST_HISTORY_QOS`
266    KeepLast,
267    /// `KEEP_ALL_HISTORY_QOS`
268    KeepAll,
269}
270
271/// `OwnershipQosPolicyKind`, DDS-DCPS 1.4 §2.2.3.12.
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
273pub enum OwnershipKind {
274    /// `SHARED_OWNERSHIP_QOS`
275    Shared,
276    /// `EXCLUSIVE_OWNERSHIP_QOS`
277    Exclusive,
278}
279
280/// `LivelinessQosPolicyKind`, DDS-DCPS 1.4 §2.2.3.14.
281#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
282pub enum LivelinessKind {
283    /// `AUTOMATIC_LIVELINESS_QOS`
284    Automatic,
285    /// `MANUAL_BY_PARTICIPANT_LIVELINESS_QOS`
286    ManualByParticipant,
287    /// `MANUAL_BY_TOPIC_LIVELINESS_QOS`
288    ManualByTopic,
289}
290
291/// `DestinationOrderQosPolicyKind`, DDS-DCPS 1.4 §2.2.3.20.
292#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
293pub enum DestinationOrderKind {
294    /// `BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS`
295    ByReceptionTimestamp,
296    /// `BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS`
297    BySourceTimestamp,
298}
299
300/// `PresentationQosPolicyAccessScopeKind`, DDS-DCPS 1.4 §2.2.3.9.
301#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
302pub enum PresentationAccessScope {
303    /// `INSTANCE_PRESENTATION_QOS`
304    Instance,
305    /// `TOPIC_PRESENTATION_QOS`
306    Topic,
307    /// `GROUP_PRESENTATION_QOS`
308    Group,
309}
310
311/// `DataRepresentationId_t`, DDS-XTypes 1.3 §7.6.3.
312#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
313pub enum DataRepresentationId {
314    /// `XCDR_DATA_REPRESENTATION`
315    Xcdr1,
316    /// `XML_DATA_REPRESENTATION`
317    Xml,
318    /// `XCDR2_DATA_REPRESENTATION`
319    Xcdr2,
320}
321
322/// `TypeConsistencyEnforcementQosPolicyKind`, DDS-XTypes 1.3 §7.6.4.
323#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
324pub enum TypeConsistencyKind {
325    /// `DISALLOW_TYPE_COERCION`
326    DisallowTypeCoercion,
327    /// `ALLOW_TYPE_COERCION`
328    AllowTypeCoercion,
329}
330
331/// One QoS policy value.
332///
333/// Every field a DDS-XML document can omit is `Option`, so an unwritten
334/// field stays distinguishable from one written at its default. A
335/// profile that inherits from another needs exactly that distinction to
336/// know which fields to take from its base. Spec §3.7.
337#[derive(Debug, Clone, PartialEq, Eq)]
338#[non_exhaustive]
339pub enum QosPolicy {
340    /// §2.2.3.4
341    UserData {
342        /// Opaque payload.
343        value: Vec<u8>,
344    },
345    /// §2.2.3.5
346    TopicData {
347        /// Opaque payload.
348        value: Vec<u8>,
349    },
350    /// §2.2.3.6
351    GroupData {
352        /// Opaque payload.
353        value: Vec<u8>,
354    },
355    /// §2.2.3.7
356    Durability {
357        /// Durability kind.
358        kind: Option<DurabilityKind>,
359    },
360    /// §2.2.3.8
361    DurabilityService {
362        /// How long a sample is kept before cleanup.
363        service_cleanup_delay: Option<Duration>,
364        /// History kind of the durability service.
365        history_kind: Option<HistoryKind>,
366        /// History depth.
367        history_depth: Option<i32>,
368        /// Sample limit.
369        max_samples: Option<i32>,
370        /// Instance limit.
371        max_instances: Option<i32>,
372        /// Per-instance sample limit.
373        max_samples_per_instance: Option<i32>,
374    },
375    /// §2.2.3.9
376    Presentation {
377        /// Access scope.
378        access_scope: Option<PresentationAccessScope>,
379        /// Whether samples are delivered coherently.
380        coherent_access: Option<bool>,
381        /// Whether ordered access is requested.
382        ordered_access: Option<bool>,
383    },
384    /// §2.2.3.10
385    Deadline {
386        /// Deadline period.
387        period: Option<Duration>,
388    },
389    /// §2.2.3.11
390    LatencyBudget {
391        /// Acceptable delay.
392        duration: Option<Duration>,
393    },
394    /// §2.2.3.12
395    Ownership {
396        /// Ownership kind.
397        kind: Option<OwnershipKind>,
398    },
399    /// §2.2.3.13
400    OwnershipStrength {
401        /// Strength value.
402        value: Option<i32>,
403    },
404    /// §2.2.3.14
405    Liveliness {
406        /// Liveliness kind.
407        kind: Option<LivelinessKind>,
408        /// Lease duration.
409        lease_duration: Option<Duration>,
410    },
411    /// §2.2.3.15
412    TimeBasedFilter {
413        /// Minimum separation between samples.
414        minimum_separation: Option<Duration>,
415    },
416    /// §2.2.3.16
417    Partition {
418        /// Partition names.
419        name: Vec<String>,
420    },
421    /// §2.2.3.17
422    Reliability {
423        /// Reliability kind.
424        kind: Option<ReliabilityKind>,
425        /// How long a write may block.
426        max_blocking_time: Option<Duration>,
427    },
428    /// §2.2.3.18
429    TransportPriority {
430        /// Priority value.
431        value: Option<i32>,
432    },
433    /// §2.2.3.19
434    Lifespan {
435        /// Sample validity.
436        duration: Option<Duration>,
437    },
438    /// §2.2.3.20
439    DestinationOrder {
440        /// Ordering kind.
441        kind: Option<DestinationOrderKind>,
442    },
443    /// §2.2.3.21
444    History {
445        /// History kind.
446        kind: Option<HistoryKind>,
447        /// History depth.
448        depth: Option<i32>,
449    },
450    /// §2.2.3.22
451    ResourceLimits {
452        /// Sample limit.
453        max_samples: Option<i32>,
454        /// Instance limit.
455        max_instances: Option<i32>,
456        /// Per-instance sample limit.
457        max_samples_per_instance: Option<i32>,
458    },
459    /// §2.2.3.23
460    EntityFactory {
461        /// Whether created entities are enabled automatically.
462        autoenable_created_entities: Option<bool>,
463    },
464    /// §2.2.3.24
465    WriterDataLifecycle {
466        /// Whether unregistered instances are disposed automatically.
467        autodispose_unregistered_instances: Option<bool>,
468    },
469    /// §2.2.3.25
470    ReaderDataLifecycle {
471        /// Delay before purging no-writer samples.
472        autopurge_nowriter_samples_delay: Option<Duration>,
473        /// Delay before purging disposed samples.
474        autopurge_disposed_samples_delay: Option<Duration>,
475    },
476    /// DDS-XTypes 1.3 §7.6.3
477    DataRepresentation {
478        /// Accepted representations, in preference order.
479        value: Vec<DataRepresentationId>,
480    },
481    /// DDS-XTypes 1.3 §7.6.4
482    TypeConsistencyEnforcement {
483        /// Coercion kind.
484        kind: Option<TypeConsistencyKind>,
485        /// Whether sequence bounds may be ignored.
486        ignore_sequence_bounds: Option<bool>,
487        /// Whether string bounds may be ignored.
488        ignore_string_bounds: Option<bool>,
489        /// Whether member names may be ignored.
490        ignore_member_names: Option<bool>,
491        /// Whether type coercion may widen.
492        prevent_type_widening: Option<bool>,
493        /// Whether a complete type object is required.
494        force_type_validation: Option<bool>,
495    },
496}
497
498impl QosPolicy {
499    /// Which policy this value carries.
500    #[must_use]
501    pub const fn kind(&self) -> QosPolicyKind {
502        match self {
503            Self::UserData { .. } => QosPolicyKind::UserData,
504            Self::TopicData { .. } => QosPolicyKind::TopicData,
505            Self::GroupData { .. } => QosPolicyKind::GroupData,
506            Self::Durability { .. } => QosPolicyKind::Durability,
507            Self::DurabilityService { .. } => QosPolicyKind::DurabilityService,
508            Self::Presentation { .. } => QosPolicyKind::Presentation,
509            Self::Deadline { .. } => QosPolicyKind::Deadline,
510            Self::LatencyBudget { .. } => QosPolicyKind::LatencyBudget,
511            Self::Ownership { .. } => QosPolicyKind::Ownership,
512            Self::OwnershipStrength { .. } => QosPolicyKind::OwnershipStrength,
513            Self::Liveliness { .. } => QosPolicyKind::Liveliness,
514            Self::TimeBasedFilter { .. } => QosPolicyKind::TimeBasedFilter,
515            Self::Partition { .. } => QosPolicyKind::Partition,
516            Self::Reliability { .. } => QosPolicyKind::Reliability,
517            Self::TransportPriority { .. } => QosPolicyKind::TransportPriority,
518            Self::Lifespan { .. } => QosPolicyKind::Lifespan,
519            Self::DestinationOrder { .. } => QosPolicyKind::DestinationOrder,
520            Self::History { .. } => QosPolicyKind::History,
521            Self::ResourceLimits { .. } => QosPolicyKind::ResourceLimits,
522            Self::EntityFactory { .. } => QosPolicyKind::EntityFactory,
523            Self::WriterDataLifecycle { .. } => QosPolicyKind::WriterDataLifecycle,
524            Self::ReaderDataLifecycle { .. } => QosPolicyKind::ReaderDataLifecycle,
525            Self::DataRepresentation { .. } => QosPolicyKind::DataRepresentation,
526            Self::TypeConsistencyEnforcement { .. } => QosPolicyKind::TypeConsistencyEnforcement,
527        }
528    }
529}