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