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
18pub trait HasQoSPolicy {
23 fn qos(&self) -> QosPolicies;
24}
25
26pub trait MutQosPolicy {
29 fn set_qos(&mut self, new_qos: &QosPolicies) -> Result<(), QosError>;
30}
31
32#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
36pub enum QosPolicyId {
37 Durability, Presentation, Deadline,
42 LatencyBudget, Ownership,
44 Liveliness,
46 TimeBasedFilter, Reliability, DestinationOrder,
54 History, ResourceLimits,
56 Lifespan,
63 Property, }
66
67#[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 }
90
91impl QosPolicyBuilder {
92 pub const fn new() -> Self {
93 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#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
218pub struct QosPolicies {
219 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 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 #[must_use]
321 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 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 if let (Some(off), Some(req)) = (self.durability, other.durability) {
366 if off < req {
367 return Some(QosPolicyId::Durability);
368 }
369 }
370
371 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 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 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 if let (Some(off), Some(req)) = (self.ownership, other.ownership) {
402 if off != req {
403 return Some(QosPolicyId::Ownership);
404 }
405 }
406
407 if let (Some(off), Some(req)) = (self.liveliness, other.liveliness) {
414 if off < req {
415 return Some(QosPolicyId::Liveliness);
416 }
417 }
418
419 if let (Some(off), Some(req)) = (self.reliability, other.reliability) {
423 if off < req {
424 return Some(QosPolicyId::Reliability);
425 }
426 }
427
428 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 None
439 }
440
441 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 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: _, } = 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 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 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, },
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 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; 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)]
633enum 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)]
646enum 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
658pub const LENGTH_UNLIMITED: i32 = -1;
663
664pub 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 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
701 pub struct Lifespan {
702 pub duration: Duration,
703 }
704
705 #[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 #[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 #[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 #[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 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
784 pub struct LatencyBudget {
785 pub duration: Duration,
786 }
787
788 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
790 pub enum Ownership {
791 Shared,
792 Exclusive { strength: i32 }, }
794
795 #[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 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 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Readable, Writable, Serialize, Deserialize)]
840 pub struct TimeBasedFilter {
841 pub minimum_separation: Duration,
842 }
843
844 #[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 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 #[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 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
902 pub enum History {
903 KeepLast { depth: i32 },
905 KeepAll,
906 }
907
908 #[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 #[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 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 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 #[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 let propagate_value: Vec<&security::Property> =
995 self.value.iter().filter(|p| p.propagate).collect();
996
997 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 let propagate_bin_value: Vec<&security::BinaryProperty> =
1010 self.binary_value.iter().filter(|p| p.propagate).collect();
1011
1012 write_pad(writer, prev_len, 4)?;
1014 writer.write_u32(propagate_bin_value.len() as u32)?;
1015 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 #[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 #[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}