rustdds/dds/
qos.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4use speedy::{Readable, Writable};
5#[allow(unused_imports)]
6use log::{debug, error, info, trace, warn};
7
8use crate::{
9  dds::result::QosError,
10  messages::submessages::elements::parameter::Parameter,
11  serialization::{
12    pl_cdr_adapters::{PlCdrDeserializeError, PlCdrSerializeError},
13    speedy_pl_cdr_helpers::*,
14  },
15  structure::{duration::Duration, endpoint::ReliabilityKind, parameter_id::ParameterId},
16};
17
18// This is to be implemented by all DomainParticipant, Publisher, Subscriber,
19// DataWriter, DataReader, Topic
20/// Trait that is implemented by all necessary DDS Entities that are required to
21/// provide QosPolicies.
22pub trait HasQoSPolicy {
23  fn qos(&self) -> QosPolicies;
24}
25
26/// Trait that is implemented by all necessary DDS Entities that are required to
27/// have a mutable QosPolicies.
28pub trait MutQosPolicy {
29  fn set_qos(&mut self, new_qos: &QosPolicies) -> Result<(), QosError>;
30}
31
32/// DDS spec 2.3.3 defines this as "long" with named constants from 0 to 22.
33/// numbering is from IDL PSM, but it should be unnecessary at the Rust
34/// application interface
35#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
36pub enum QosPolicyId {
37  // Invalid  // We should represent this using Option<QosPolicyId> where needed
38  // UserData,  // 1
39  Durability,   // 2
40  Presentation, // 3
41  Deadline,
42  LatencyBudget, // 5
43  Ownership,
44  // OwnershipStrength, // 7
45  Liveliness,
46  TimeBasedFilter, // 9
47  // Partition,
48
49  // Note: If "Partition" is ever implemented, observe also DDS Security spec v1.1
50  // Section "7.3.5 Immutability of Publisher Partition Qos in combination with non-volatile
51  // Durability kind" when implementing.
52  Reliability, // 11
53  DestinationOrder,
54  History, // 13
55  ResourceLimits,
56  // EntityFactory, // 15
57  // WriterDataLifeCycle,
58  // ReaderDataLifeCycle, // 17
59  // TopicData, // 18
60  // GroupData,
61  // TransportPriority, // 20
62  Lifespan,
63  // DurabilityService, // 22
64  Property, // No Id in the security spec (But this is from older DDS/RTPs spec.)
65}
66
67/// Utility for building [QosPolicies]
68#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
69pub struct QosPolicyBuilder {
70  durability: Option<policy::Durability>,
71  presentation: Option<policy::Presentation>,
72  deadline: Option<policy::Deadline>,
73  latency_budget: Option<policy::LatencyBudget>,
74  ownership: Option<policy::Ownership>,
75  liveliness: Option<policy::Liveliness>,
76  time_based_filter: Option<policy::TimeBasedFilter>,
77  reliability: Option<policy::Reliability>,
78  destination_order: Option<policy::DestinationOrder>,
79  history: Option<policy::History>,
80  resource_limits: Option<policy::ResourceLimits>,
81  lifespan: Option<policy::Lifespan>,
82  #[cfg(feature = "security")]
83  property: Option<policy::Property>,
84}
85
86impl QosPolicyBuilder {
87  pub fn new() -> Self {
88    Self::default()
89  }
90
91  #[must_use]
92  pub const fn durability(mut self, durability: policy::Durability) -> Self {
93    self.durability = Some(durability);
94    self
95  }
96
97  #[must_use]
98  pub const fn presentation(mut self, presentation: policy::Presentation) -> Self {
99    self.presentation = Some(presentation);
100    self
101  }
102
103  #[must_use]
104  pub const fn deadline(mut self, deadline: policy::Deadline) -> Self {
105    self.deadline = Some(deadline);
106    self
107  }
108
109  #[must_use]
110  pub const fn latency_budget(mut self, latency_budget: policy::LatencyBudget) -> Self {
111    self.latency_budget = Some(latency_budget);
112    self
113  }
114
115  #[must_use]
116  pub const fn ownership(mut self, ownership: policy::Ownership) -> Self {
117    self.ownership = Some(ownership);
118    self
119  }
120
121  #[must_use]
122  pub const fn liveliness(mut self, liveliness: policy::Liveliness) -> Self {
123    self.liveliness = Some(liveliness);
124    self
125  }
126
127  #[must_use]
128  pub const fn time_based_filter(mut self, time_based_filter: policy::TimeBasedFilter) -> Self {
129    self.time_based_filter = Some(time_based_filter);
130    self
131  }
132
133  #[must_use]
134  pub const fn reliability(mut self, reliability: policy::Reliability) -> Self {
135    self.reliability = Some(reliability);
136    self
137  }
138
139  #[must_use]
140  pub const fn best_effort(mut self) -> Self {
141    self.reliability = Some(policy::Reliability::BestEffort);
142    self
143  }
144
145  #[must_use]
146  pub const fn reliable(mut self, max_blocking_time: Duration) -> Self {
147    self.reliability = Some(policy::Reliability::Reliable { max_blocking_time });
148    self
149  }
150
151  #[must_use]
152  pub const fn destination_order(mut self, destination_order: policy::DestinationOrder) -> Self {
153    self.destination_order = Some(destination_order);
154    self
155  }
156
157  #[must_use]
158  pub const fn history(mut self, history: policy::History) -> Self {
159    self.history = Some(history);
160    self
161  }
162
163  #[must_use]
164  pub const fn resource_limits(mut self, resource_limits: policy::ResourceLimits) -> Self {
165    self.resource_limits = Some(resource_limits);
166    self
167  }
168
169  #[must_use]
170  pub const fn lifespan(mut self, lifespan: policy::Lifespan) -> Self {
171    self.lifespan = Some(lifespan);
172    self
173  }
174
175  #[cfg(feature = "security")]
176  #[must_use]
177  pub fn property(mut self, property: policy::Property) -> Self {
178    self.property = Some(property);
179    self
180  }
181
182  pub fn build(self) -> QosPolicies {
183    QosPolicies {
184      durability: self.durability,
185      presentation: self.presentation,
186      deadline: self.deadline,
187      latency_budget: self.latency_budget,
188      ownership: self.ownership,
189      liveliness: self.liveliness,
190      time_based_filter: self.time_based_filter,
191      reliability: self.reliability,
192      destination_order: self.destination_order,
193      history: self.history,
194      resource_limits: self.resource_limits,
195      lifespan: self.lifespan,
196      #[cfg(feature = "security")]
197      property: self.property,
198    }
199  }
200}
201
202/// Describes a set of RTPS/DDS QoS policies
203///
204/// QosPolicies are constructed using a [`QosPolicyBuilder`]
205#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
206pub struct QosPolicies {
207  // pub(crate) because as we want to have some builtin QoS Policies as constant.
208  pub(crate) durability: Option<policy::Durability>,
209  pub(crate) presentation: Option<policy::Presentation>,
210  pub(crate) deadline: Option<policy::Deadline>,
211  pub(crate) latency_budget: Option<policy::LatencyBudget>,
212  pub(crate) ownership: Option<policy::Ownership>,
213  pub(crate) liveliness: Option<policy::Liveliness>,
214  pub(crate) time_based_filter: Option<policy::TimeBasedFilter>,
215  pub(crate) reliability: Option<policy::Reliability>,
216  pub(crate) destination_order: Option<policy::DestinationOrder>,
217  pub(crate) history: Option<policy::History>,
218  pub(crate) resource_limits: Option<policy::ResourceLimits>,
219  pub(crate) lifespan: Option<policy::Lifespan>,
220  #[cfg(feature = "security")]
221  pub(crate) property: Option<policy::Property>,
222}
223
224impl QosPolicies {
225  // TODO: rename this to "none", as this is already member of QosPolicies, so
226  // context in implied
227  pub fn qos_none() -> Self {
228    Self::default()
229  }
230
231  pub fn builder() -> QosPolicyBuilder {
232    QosPolicyBuilder::new()
233  }
234
235  pub const fn durability(&self) -> Option<policy::Durability> {
236    self.durability
237  }
238
239  pub fn is_volatile(&self) -> bool {
240    matches!(self.durability, Some(policy::Durability::Volatile))
241  }
242
243  pub const fn presentation(&self) -> Option<policy::Presentation> {
244    self.presentation
245  }
246
247  pub const fn deadline(&self) -> Option<policy::Deadline> {
248    self.deadline
249  }
250
251  pub const fn latency_budget(&self) -> Option<policy::LatencyBudget> {
252    self.latency_budget
253  }
254
255  pub const fn ownership(&self) -> Option<policy::Ownership> {
256    self.ownership
257  }
258
259  pub const fn liveliness(&self) -> Option<policy::Liveliness> {
260    self.liveliness
261  }
262
263  pub const fn time_based_filter(&self) -> Option<policy::TimeBasedFilter> {
264    self.time_based_filter
265  }
266
267  pub const fn reliability(&self) -> Option<policy::Reliability> {
268    self.reliability
269  }
270
271  pub fn is_reliable(&self) -> bool {
272    matches!(self.reliability, Some(policy::Reliability::Reliable { .. }))
273  }
274
275  pub const fn reliable_max_blocking_time(&self) -> Option<Duration> {
276    if let Some(policy::Reliability::Reliable { max_blocking_time }) = self.reliability {
277      Some(max_blocking_time)
278    } else {
279      None
280    }
281  }
282
283  pub const fn destination_order(&self) -> Option<policy::DestinationOrder> {
284    self.destination_order
285  }
286
287  pub const fn history(&self) -> Option<policy::History> {
288    self.history
289  }
290
291  pub const fn resource_limits(&self) -> Option<policy::ResourceLimits> {
292    self.resource_limits
293  }
294
295  pub const fn lifespan(&self) -> Option<policy::Lifespan> {
296    self.lifespan
297  }
298
299  #[cfg(feature = "security")]
300  pub fn property(&self) -> Option<policy::Property> {
301    self.property.clone()
302  }
303
304  /// Merge two QosPolicies
305  ///
306  /// Constructs a QosPolicy, where each policy is taken from `self`,
307  /// and overwritten with those policies from `other` that are defined.
308  #[must_use]
309  pub fn modify_by(&self, other: &Self) -> Self {
310    Self {
311      durability: other.durability.or(self.durability),
312      presentation: other.presentation.or(self.presentation),
313      deadline: other.deadline.or(self.deadline),
314      latency_budget: other.latency_budget.or(self.latency_budget),
315      ownership: other.ownership.or(self.ownership),
316      liveliness: other.liveliness.or(self.liveliness),
317      time_based_filter: other.time_based_filter.or(self.time_based_filter),
318      reliability: other.reliability.or(self.reliability),
319      destination_order: other.destination_order.or(self.destination_order),
320      history: other.history.or(self.history),
321      resource_limits: other.resource_limits.or(self.resource_limits),
322      lifespan: other.lifespan.or(self.lifespan),
323      #[cfg(feature = "security")]
324      property: other.property.clone().or(self.property.clone()),
325    }
326  }
327
328  /// Check if policy complies to another policy.
329  ///
330  /// `self` is the "offered" (publisher) QoS
331  /// `other` is the "requested" (subscriber) QoS
332  ///
333  /// * None => Policies are compatible
334  /// * Some(policyId) => Failure, where policyId is (any) one of the policies
335  ///   causing incompliance
336  ///
337  /// Compliance (compatibility) is defined in the table in DDS spec v1.4
338  /// Section "2.2.3 Supported QoS"
339  ///
340  /// This is not symmetric.
341  pub fn compliance_failure_wrt(&self, other: &Self) -> Option<QosPolicyId> {
342    trace!("QoS compatibility check - offered: {self:?} - requested {other:?}");
343    let result = self.compliance_failure_wrt_impl(other);
344    trace!("Result: {result:?}");
345    result
346  }
347
348  fn compliance_failure_wrt_impl(&self, other: &Self) -> Option<QosPolicyId> {
349    // TODO: Check for cases where policy is requested, but not offered (None)
350
351    // check Durability: Offered must be better than or equal to Requested.
352    if let (Some(off), Some(req)) = (self.durability, other.durability) {
353      if off < req {
354        return Some(QosPolicyId::Durability);
355      }
356    }
357
358    // check Presentation:
359    // * If coherent_access is requested, it must be offered also. AND
360    // * Same for ordered_access. AND
361    // * Offered access scope is broader than requested.
362    if let (Some(off), Some(req)) = (self.presentation, other.presentation) {
363      if (req.coherent_access && !off.coherent_access)
364        || (req.ordered_access && !off.ordered_access)
365        || (req.access_scope > off.access_scope)
366      {
367        return Some(QosPolicyId::Presentation);
368      }
369    }
370
371    // check Deadline: offered period <= requested period
372    if let (Some(off), Some(req)) = (self.deadline, other.deadline) {
373      if off.0 > req.0 {
374        return Some(QosPolicyId::Deadline);
375      }
376    }
377
378    // check Latency Budget:
379    // offered duration <= requested duration
380    if let (Some(off), Some(req)) = (self.latency_budget, other.latency_budget) {
381      if off.duration > req.duration {
382        return Some(QosPolicyId::LatencyBudget);
383      }
384    }
385
386    // check Ownership:
387    // offered kind == requested kind
388    if let (Some(off), Some(req)) = (self.ownership, other.ownership) {
389      if off != req {
390        return Some(QosPolicyId::Ownership);
391      }
392    }
393
394    // check Liveliness
395    // offered kind >= requested kind
396    // Definition: AUTOMATIC < MANUAL_BY_PARTICIPANT < MANUAL_BY_TOPIC
397    // AND offered lease_duration <= requested lease_duration
398    //
399    // See Ord implementation on Liveliness.
400    if let (Some(off), Some(req)) = (self.liveliness, other.liveliness) {
401      if off < req {
402        return Some(QosPolicyId::Liveliness);
403      }
404    }
405
406    // check Reliability
407    // offered kind >= requested kind
408    // kind ranking: BEST_EFFORT < RELIABLE
409    if let (Some(off), Some(req)) = (self.reliability, other.reliability) {
410      if off < req {
411        return Some(QosPolicyId::Reliability);
412      }
413    }
414
415    // check Destination Order
416    // offered kind >= requested kind
417    // kind ranking: BY_RECEPTION_TIMESTAMP < BY_SOURCE_TIMESTAMP
418    if let (Some(off), Some(req)) = (self.destination_order, other.destination_order) {
419      if off < req {
420        return Some(QosPolicyId::DestinationOrder);
421      }
422    }
423
424    // default value. no incompatibility detected.
425    None
426  }
427
428  // serialization
429  pub fn to_parameter_list(
430    &self,
431    ctx: speedy::Endianness,
432  ) -> Result<Vec<Parameter>, PlCdrSerializeError> {
433    let mut pl = Vec::with_capacity(8);
434
435    let QosPolicies {
436      // bind self to (a) destructure, and (b) ensure all fields are handled
437      durability,
438      presentation,
439      deadline,
440      latency_budget,
441      ownership,
442      liveliness,
443      time_based_filter,
444      reliability,
445      destination_order,
446      history,
447      resource_limits,
448      lifespan,
449      #[cfg(feature = "security")]
450        property: _, // TODO: properties to parameter list?
451    } = self;
452
453    macro_rules! emit {
454      ($pid:ident, $member:expr, $type:ty) => {
455        pl.push(Parameter::new(ParameterId::$pid, {
456          let m: &$type = $member;
457          m.write_to_vec_with_ctx(ctx)?
458        }))
459      };
460    }
461    macro_rules! emit_option {
462      ($pid:ident, $member:expr, $type:ty) => {
463        if let Some(m) = $member {
464          emit!($pid, m, $type)
465        }
466      };
467    }
468
469    use policy::*;
470
471    emit_option!(PID_DURABILITY, durability, Durability);
472    emit_option!(PID_PRESENTATION, presentation, Presentation);
473    emit_option!(PID_DEADLINE, deadline, Deadline);
474    emit_option!(PID_LATENCY_BUDGET, latency_budget, LatencyBudget);
475
476    // Ownership serializes to (maybe) two separate Parameters
477    match ownership {
478      Some(Ownership::Exclusive { strength }) => {
479        emit!(PID_OWNERSHIP, &OwnershipKind::Exclusive, OwnershipKind);
480        emit!(PID_OWNERSHIP_STRENGTH, strength, i32);
481      }
482      Some(Ownership::Shared) => {
483        emit!(PID_OWNERSHIP, &OwnershipKind::Shared, OwnershipKind);
484      }
485      None => (),
486    }
487    // This should serialize as is
488    emit_option!(PID_LIVELINESS, liveliness, policy::Liveliness);
489    emit_option!(
490      PID_TIME_BASED_FILTER,
491      time_based_filter,
492      policy::TimeBasedFilter
493    );
494
495    if let Some(rel) = reliability.as_ref() {
496      let reliability_ser = match rel {
497        Reliability::BestEffort => ReliabilitySerialization {
498          reliability_kind: ReliabilityKind::BestEffort,
499          max_blocking_time: Duration::ZERO, // dummy value for serialization
500        },
501        Reliability::Reliable { max_blocking_time } => ReliabilitySerialization {
502          reliability_kind: ReliabilityKind::Reliable,
503          max_blocking_time: *max_blocking_time,
504        },
505      };
506      emit!(PID_RELIABILITY, &reliability_ser, ReliabilitySerialization);
507    }
508
509    emit_option!(
510      PID_DESTINATION_ORDER,
511      destination_order,
512      policy::DestinationOrder
513    );
514
515    if let Some(history) = history.as_ref() {
516      let history_ser = match history {
517        History::KeepLast { depth } => HistorySerialization {
518          kind: HistoryKind::KeepLast,
519          depth: *depth,
520        },
521        History::KeepAll => HistorySerialization {
522          kind: HistoryKind::KeepAll,
523          depth: 0,
524        },
525      };
526      emit!(PID_HISTORY, &history_ser, HistorySerialization);
527    }
528    emit_option!(PID_RESOURCE_LIMITS, resource_limits, policy::ResourceLimits);
529    emit_option!(PID_LIFESPAN, lifespan, policy::Lifespan);
530
531    Ok(pl)
532  }
533
534  pub fn from_parameter_list(
535    ctx: speedy::Endianness,
536    pl_map: &BTreeMap<ParameterId, Vec<&Parameter>>,
537  ) -> Result<QosPolicies, PlCdrDeserializeError> {
538    macro_rules! get_option {
539      ($pid:ident) => {
540        get_option_from_pl_map(pl_map, ctx, ParameterId::$pid, "<not_used>")?
541      };
542    }
543
544    let durability: Option<policy::Durability> = get_option!(PID_DURABILITY);
545    let presentation: Option<policy::Presentation> = get_option!(PID_PRESENTATION);
546    let deadline: Option<policy::Deadline> = get_option!(PID_DEADLINE);
547    let latency_budget: Option<policy::LatencyBudget> = get_option!(PID_LATENCY_BUDGET);
548
549    // Ownership is in 2 parts
550    let ownership_kind: Option<OwnershipKind> = get_option!(PID_OWNERSHIP);
551    let ownership_strength: Option<i32> = get_option!(PID_OWNERSHIP_STRENGTH);
552    let ownership = match (ownership_kind, ownership_strength) {
553      (Some(OwnershipKind::Shared), None) => Some(policy::Ownership::Shared),
554      (Some(OwnershipKind::Shared), Some(_strength)) => {
555        warn!("QosPolicies deserializer: Received OwnershipKind::Shared and a strength value.");
556        None
557      }
558      (Some(OwnershipKind::Exclusive), Some(strength)) => {
559        Some(policy::Ownership::Exclusive { strength })
560      }
561      (Some(OwnershipKind::Exclusive), None) => {
562        warn!("QosPolicies deserializer: Received OwnershipKind::Exclusive but no strength value.");
563        None
564      }
565      (None, Some(_strength)) => {
566        warn!(
567          "QosPolicies deserializer: Received ownership strength value, but no kind parameter."
568        );
569        None
570      }
571      (None, None) => None,
572    };
573
574    let reliability_ser: Option<ReliabilitySerialization> = get_option!(PID_RELIABILITY);
575    let reliability = reliability_ser.map(|rs| match rs.reliability_kind {
576      ReliabilityKind::BestEffort => policy::Reliability::BestEffort,
577      ReliabilityKind::Reliable => policy::Reliability::Reliable {
578        max_blocking_time: rs.max_blocking_time,
579      },
580    });
581    let destination_order: Option<policy::DestinationOrder> = get_option!(PID_DESTINATION_ORDER);
582
583    let history_ser: Option<HistorySerialization> = get_option!(PID_HISTORY);
584    let history = history_ser.map(|h| match h.kind {
585      HistoryKind::KeepAll => policy::History::KeepAll,
586      HistoryKind::KeepLast => policy::History::KeepLast { depth: h.depth },
587    });
588
589    let liveliness: Option<policy::Liveliness> = get_option!(PID_LIVELINESS);
590    let time_based_filter: Option<policy::TimeBasedFilter> = get_option!(PID_TIME_BASED_FILTER);
591
592    let resource_limits: Option<policy::ResourceLimits> = get_option!(PID_RESOURCE_LIMITS);
593    let lifespan: Option<policy::Lifespan> = get_option!(PID_LIFESPAN);
594
595    #[cfg(feature = "security")]
596    let property: Option<policy::Property> = None; // TODO: Should also properties be read?
597
598    // We construct using the struct syntax directly rather than the builder,
599    // so we cannot forget any field.
600    Ok(QosPolicies {
601      durability,
602      presentation,
603      deadline,
604      latency_budget,
605      ownership,
606      liveliness,
607      time_based_filter,
608      reliability,
609      destination_order,
610      history,
611      resource_limits,
612      lifespan,
613      #[cfg(feature = "security")]
614      property,
615    })
616  }
617}
618
619#[derive(Writable, Readable, Clone)]
620//#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
621enum HistoryKind {
622  KeepLast,
623  KeepAll,
624}
625
626#[derive(Writable, Readable, Clone)]
627struct HistorySerialization {
628  pub kind: HistoryKind,
629  pub depth: i32,
630}
631
632#[derive(Writable, Readable)]
633//#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
634enum OwnershipKind {
635  Shared,
636  Exclusive,
637}
638
639#[derive(Writable, Readable, Clone)]
640struct ReliabilitySerialization {
641  pub reliability_kind: ReliabilityKind,
642  pub max_blocking_time: Duration,
643}
644
645// DDS spec v1.4 p.139
646// TODO: Replace this with Option construct so that
647// None means no limit and Some(limit) gives the limit when defined.
648// Use is in resource_limits.
649pub const LENGTH_UNLIMITED: i32 = -1;
650
651// put these into a submodule to avoid repeating the word "policy" or
652// "qospolicy"
653/// Contains all available QoSPolicies
654pub mod policy {
655  use std::cmp::Ordering;
656
657  use speedy::{Readable, Writable};
658  use serde::{Deserialize, Serialize};
659  #[allow(unused_imports)]
660  use log::{debug, error, info, trace, warn};
661  #[cfg(feature = "security")]
662  use speedy::{Context, IsEof, Reader, Writer};
663
664  use crate::structure::duration::Duration;
665  #[cfg(feature = "security")]
666  use crate::serialization::speedy_pl_cdr_helpers::*;
667
668  /*
669  pub struct UserData {
670    pub value: Vec<u8>,
671  }
672
673  pub struct TopicData {
674    pub value: Vec<u8>,
675  }
676
677  pub struct GroupData {
678    pub value: Vec<u8>,
679  }
680
681  pub struct TransportPriority {
682    pub value: i32,
683  }
684  */
685
686  /// DDS 2.2.3.16 LIFESPAN
687  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
688  pub struct Lifespan {
689    pub duration: Duration,
690  }
691
692  /// DDS 2.2.3.4 DURABILITY
693  ///
694  /// DDS Spec 1.4:
695  ///
696  /// "This QoS policy controls whether the Service will actually make data
697  /// available to late-joining readers. Note that although related, this does
698  /// not strictly control what data the Service will maintain internally. That
699  /// is, the Service may choose to maintain some data for its own purposes
700  /// (e.g., flow control) and yet not make it available to late-joining readers
701  /// if the DURABILITY QoS policy is set to VOLATILE."
702  #[derive(
703    Copy,
704    Clone,
705    Debug,
706    PartialEq,
707    Eq,
708    PartialOrd,
709    Ord,
710    Hash,
711    Readable,
712    Writable,
713    Serialize,
714    Deserialize,
715  )]
716  pub enum Durability {
717    Volatile,
718    TransientLocal,
719    Transient,
720    Persistent,
721  }
722
723  /// DDS 2.2.3.6 PRESENTATION
724  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
725  pub struct Presentation {
726    pub access_scope: PresentationAccessScope,
727    pub coherent_access: bool,
728    pub ordered_access: bool,
729  }
730
731  /// Access scope that is part of DDS 2.2.3.6 PRESENTATION
732  #[derive(
733    Copy,
734    Clone,
735    Debug,
736    PartialEq,
737    Eq,
738    PartialOrd,
739    Ord,
740    Hash,
741    Readable,
742    Writable,
743    Serialize,
744    Deserialize,
745  )]
746  pub enum PresentationAccessScope {
747    Instance,
748    Topic,
749    Group,
750  }
751
752  /// DDS 2.2.3.7 DEADLINE
753  #[derive(
754    Copy,
755    Clone,
756    Debug,
757    PartialEq,
758    Eq,
759    Ord,
760    PartialOrd,
761    Hash,
762    Readable,
763    Writable,
764    Serialize,
765    Deserialize,
766  )]
767  pub struct Deadline(pub Duration);
768
769  /// DDS 2.2.3.8 LATENCY_BUDGET
770  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
771  pub struct LatencyBudget {
772    pub duration: Duration,
773  }
774
775  /// DDS 2.2.3.9 OWNERSHIP
776  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
777  pub enum Ownership {
778    Shared,
779    Exclusive { strength: i32 }, // This also implements OwnershipStrength
780  }
781
782  /// DDS 2.2.3.11 LIVELINESS
783  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
784  pub enum Liveliness {
785    Automatic { lease_duration: Duration },
786    ManualByParticipant { lease_duration: Duration },
787    ManualByTopic { lease_duration: Duration },
788  }
789
790  impl Liveliness {
791    fn kind_num(&self) -> i32 {
792      match self {
793        Self::Automatic { .. } => 0,
794        Self::ManualByParticipant { .. } => 1,
795        Self::ManualByTopic { .. } => 2,
796      }
797    }
798
799    pub fn duration(&self) -> Duration {
800      match self {
801        Self::Automatic { lease_duration }
802        | Self::ManualByParticipant { lease_duration }
803        | Self::ManualByTopic { lease_duration } => *lease_duration,
804      }
805    }
806  }
807
808  impl Ord for Liveliness {
809    fn cmp(&self, other: &Self) -> Ordering {
810      // Manual liveliness is greater than automatic, but
811      // duration compares in reverse
812      other
813        .kind_num()
814        .cmp(&other.kind_num())
815        .then_with(|| self.duration().cmp(&other.duration()).reverse())
816    }
817  }
818
819  impl PartialOrd for Liveliness {
820    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
821      Some(self.cmp(other))
822    }
823  }
824
825  /// DDS 2.2.3.12 TIME_BASED_FILTER
826  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
827  pub struct TimeBasedFilter {
828    pub minimum_separation: Duration,
829  }
830
831  /*
832  pub struct Partition {
833    pub name: Vec<Vec<u8>>,
834  }
835  */
836
837  /// DDS 2.2.3.14 RELIABILITY
838  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
839  pub enum Reliability {
840    BestEffort,
841    Reliable { max_blocking_time: Duration },
842  }
843
844  impl Ord for Reliability {
845    // max_blocking_time is not compared.
846    // TODO: This is kind of bad, because now Eq and Ord are inconsistent:
847    // If we have A and B both Reliability::Reliable, but with different
848    // max_blocking_time, then Ord will say they are Ordering::Equal,
849    // but Eq will say they are not equal.
850    fn cmp(&self, other: &Self) -> Ordering {
851      match (self, other) {
852        (Self::BestEffort, Self::BestEffort) | (Self::Reliable { .. }, Self::Reliable { .. }) => {
853          Ordering::Equal
854        }
855        (Self::BestEffort, Self::Reliable { .. }) => Ordering::Less,
856        (Self::Reliable { .. }, Self::BestEffort) => Ordering::Greater,
857      }
858    }
859  }
860
861  impl PartialOrd for Reliability {
862    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
863      Some(self.cmp(other))
864    }
865  }
866
867  /// DDS 2.2.3.17 DESTINATION_ORDER
868  #[derive(
869    Copy,
870    Clone,
871    Debug,
872    PartialEq,
873    Eq,
874    Ord,
875    PartialOrd,
876    Hash,
877    Readable,
878    Writable,
879    Serialize,
880    Deserialize,
881  )]
882  pub enum DestinationOrder {
883    ByReceptionTimestamp,
884    BySourceTimeStamp,
885  }
886
887  /// DDS 2.2.3.18 HISTORY
888  #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
889  pub enum History {
890    // Variants must be in this order ot derive Ord correctly.
891    KeepLast { depth: i32 },
892    KeepAll,
893  }
894
895  /// DDS Spec v1.4 Section 2.2.3.19 RESOURCE_LIMITS
896  ///
897  /// DDS Spec v1.4 p.147 "struct ResourceLimitsQosPolicy" defines the
898  /// fields as "long". The "long" type of OMG IDL is defined to have
899  /// 32-bit (signed, 2's complement) range in the OMG IDL spec v4.2, Table
900  /// 7-13: Integer Types.
901  ///
902  /// But it does not make sense to have negative limits, so these should be
903  /// unsigned.
904  ///
905  /// Negative values are needed, because DDS spec defines the special value
906  /// const long LENGTH_UNLIMITED = -1;
907  #[derive(Copy, Clone, Debug, PartialEq, Eq, Writable, Readable, Serialize, Deserialize)]
908  pub struct ResourceLimits {
909    pub max_samples: i32,
910    pub max_instances: i32,
911    pub max_samples_per_instance: i32,
912  }
913
914  #[cfg(feature = "security")]
915  use crate::security;
916  // DDS Security spec v1.1
917  // Section 7.2.5 PropertyQosPolicy, DomainParticipantQos, DataWriterQos, and
918  // DataReaderQos
919  #[cfg(feature = "security")]
920  #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
921  pub struct Property {
922    pub value: Vec<security::types::Property>,
923    pub binary_value: Vec<security::types::BinaryProperty>,
924  }
925
926  #[cfg(feature = "security")]
927  impl<'a, C: Context> Readable<'a, C> for Property {
928    fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
929      let count = reader.read_u32()?;
930      let mut value = Vec::new();
931
932      let mut prev_len = 0;
933      for _ in 0..count {
934        read_pad(reader, prev_len, 4)?;
935        let s: security::types::Property = reader.read_value()?;
936        prev_len = s.serialized_len();
937        value.push(s);
938      }
939
940      // Depending on the RTPS version used by writer, PropertyQoSPolicy may end here,
941      // i.e. there is no "binary_value". Pad should still always exist.
942      read_pad(reader, prev_len, 4)?;
943      let mut binary_value = Vec::new();
944
945      match reader.read_u32() {
946        Ok(count) => {
947          prev_len = 0;
948          for _ in 0..count {
949            read_pad(reader, prev_len, 4)?;
950            let s: security::types::BinaryProperty = reader.read_value()?;
951            prev_len = s.serialized_len();
952            binary_value.push(s);
953          }
954        }
955        Err(e) => {
956          if e.is_eof() {
957            // This is ok. Only String properties, no binary.
958            debug!("Non-security PropertyQosPolicy");
959          } else {
960            return Err(e);
961          }
962        }
963      }
964
965      Ok(Property {
966        value,
967        binary_value,
968      })
969    }
970  }
971
972  // Writing several strings is a bit complicated, because
973  // we have to keep track of alignment.
974  // Again, alignment comes BEFORE string length, or vector item count, not after
975  // string.
976  #[cfg(feature = "security")]
977  impl<C: Context> Writable<C> for Property {
978    fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
979      // First self.value
980      // Only those properties with propagate=true are written
981      let propagate_value: Vec<&security::Property> =
982        self.value.iter().filter(|p| p.propagate).collect();
983
984      // propagate_value vector length
985      writer.write_u32(propagate_value.len() as u32)?;
986
987      let mut prev_len = 0;
988      for prop in propagate_value {
989        write_pad(writer, prev_len, 4)?;
990        writer.write_value(prop)?;
991        prev_len = prop.serialized_len();
992      }
993
994      // Then self.bin_value
995      // Only those binary properties with propagate=true are written
996      let propagate_bin_value: Vec<&security::BinaryProperty> =
997        self.binary_value.iter().filter(|p| p.propagate).collect();
998
999      // propagate_bin_value vector length
1000      write_pad(writer, prev_len, 4)?;
1001      writer.write_u32(propagate_bin_value.len() as u32)?;
1002      // and the elements
1003      let mut prev_len = 0;
1004      for prop in propagate_bin_value {
1005        write_pad(writer, prev_len, 4)?;
1006        writer.write_value(prop)?;
1007        prev_len = prop.serialized_len();
1008      }
1009
1010      Ok(())
1011    }
1012  }
1013
1014  // DDS Security spec v1.1
1015  // Section 7.2.5 PropertyQosPolicy, DomainParticipantQos, DataWriterQos, and
1016  // DataReaderQos
1017  //
1018  // so this is DataTagQosPolicy, which is an alias for "DataTags"
1019  // We call it qos::policy::DataTag
1020  #[derive(Clone, Debug, PartialEq, Eq, Default)]
1021  #[cfg(feature = "security")]
1022  pub struct DataTag {
1023    pub tags: Vec<security::types::Tag>,
1024  }
1025
1026  #[cfg(feature = "security")]
1027  impl<'a, C: Context> Readable<'a, C> for DataTag {
1028    fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
1029      let count = reader.read_u32()?;
1030      let mut tags = Vec::new();
1031
1032      let mut prev_len = 0;
1033      for _ in 0..count {
1034        read_pad(reader, prev_len, 4)?;
1035        let s: security::types::Tag = reader.read_value()?;
1036        prev_len = s.serialized_len();
1037        tags.push(s);
1038      }
1039      Ok(DataTag { tags })
1040    }
1041  }
1042
1043  // Writing several strings is a bit complicated, because
1044  // we have to keep track of alignment.
1045  // Again, alignment comes BEFORE string length, or vector item count, not after
1046  // string.
1047  #[cfg(feature = "security")]
1048  impl<C: Context> Writable<C> for DataTag {
1049    fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
1050      writer.write_u32(self.tags.len() as u32)?;
1051
1052      let mut prev_len = 0;
1053      for tag in &self.tags {
1054        write_pad(writer, prev_len, 4)?;
1055        writer.write_value(tag)?;
1056        prev_len = tag.serialized_len();
1057      }
1058      Ok(())
1059    }
1060  }
1061} // mod policy