1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
use core::cmp::Ordering;

use crate::infrastructure::time::{Duration, DurationKind, DURATION_ZERO};

pub type QosPolicyId = i32;
#[derive(Debug, PartialEq, Eq, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub enum Length {
    Unlimited,
    Limited(u32),
}

impl PartialOrd for Length {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match self {
            Length::Unlimited => match other {
                Length::Unlimited => Some(Ordering::Equal),
                Length::Limited(_) => Some(Ordering::Greater),
            },
            Length::Limited(value) => match other {
                Length::Unlimited => Some(Ordering::Less),
                Length::Limited(other) => value.partial_cmp(other),
            },
        }
    }
}

impl PartialEq<usize> for Length {
    fn eq(&self, other: &usize) -> bool {
        match self {
            Length::Unlimited => false,
            Length::Limited(value) => (*value as usize).eq(other),
        }
    }
}

impl PartialOrd<usize> for Length {
    fn partial_cmp(&self, other: &usize) -> Option<Ordering> {
        match self {
            Length::Unlimited => Some(Ordering::Greater),
            Length::Limited(value) => (*value as usize).partial_cmp(other),
        }
    }
}

impl PartialEq<Length> for usize {
    fn eq(&self, other: &Length) -> bool {
        match other {
            Length::Unlimited => false,
            Length::Limited(value) => self.eq(&(*value as usize)),
        }
    }
}

impl PartialOrd<Length> for usize {
    fn partial_cmp(&self, other: &Length) -> Option<Ordering> {
        match other {
            Length::Unlimited => Some(Ordering::Less),
            Length::Limited(value) => self.partial_cmp(&(*value as usize)),
        }
    }
}

/// This class is the abstract root for all the QoS policies.
/// It provides the basic mechanism for an application to specify quality of service parameters. It has an attribute name that is used
/// to identify uniquely each QoS policy. All concrete QosPolicy classes derive from this root and include a value whose type
/// depends on the concrete QoS policy.
/// The type of a QosPolicy value may be atomic, such as an integer or float, or compound (a structure). Compound types are used
/// whenever multiple parameters must be set coherently to define a consistent value for a QosPolicy.
/// Each Entity can be configured with a list of QosPolicy. However, any Entity cannot support any QosPolicy. For instance, a
/// DomainParticipant supports different QosPolicy than a Topic or a Publisher.
/// QosPolicy can be set when the Entity is created, or modified with the set_qos method. Each QosPolicy in the list is treated
/// independently from the others. This approach has the advantage of being very extensible. However, there may be cases where
/// several policies are in conflict. Consistency checking is performed each time the policies are modified via the set_qos
/// operation.
/// When a policy is changed after being set to a given value, it is not required that the new value be applied instantaneously; the
/// Service is allowed to apply it after a transition phase. In addition, some QosPolicy have “immutable” semantics meaning that
/// they can only be specified either at Entity creation time or else prior to calling the enable operation on the Entity.
/// Sub clause 2.2.3, Supported QoS provides the list of all QosPolicy, their meaning, characteristics and possible values, as well
/// as the concrete Entity to which they apply.
pub trait QosPolicy {
    fn name(&self) -> &str;
}

const USERDATA_QOS_POLICY_NAME: &str = "UserData";
const DURABILITY_QOS_POLICY_NAME: &str = "Durability";
const PRESENTATION_QOS_POLICY_NAME: &str = "Presentation";
const DEADLINE_QOS_POLICY_NAME: &str = "Deadline";
const LATENCYBUDGET_QOS_POLICY_NAME: &str = "LatencyBudget";
const OWNERSHIP_QOS_POLICY_NAME: &str = "Ownership";
const LIVELINESS_QOS_POLICY_NAME: &str = "Liveliness";
const TIMEBASEDFILTER_QOS_POLICY_NAME: &str = "TimeBasedFilter";
const PARTITION_QOS_POLICY_NAME: &str = "Partition";
const RELIABILITY_QOS_POLICY_NAME: &str = "Reliability";
const DESTINATIONORDER_QOS_POLICY_NAME: &str = "DestinationOrder";
const HISTORY_QOS_POLICY_NAME: &str = "History";
const RESOURCELIMITS_QOS_POLICY_NAME: &str = "ResourceLimits";
const ENTITYFACTORY_QOS_POLICY_NAME: &str = "EntityFactory";
const WRITERDATALIFECYCLE_QOS_POLICY_NAME: &str = "WriterDataLifecycle";
const READERDATALIFECYCLE_QOS_POLICY_NAME: &str = "ReaderDataLifecycle";
const TOPICDATA_QOS_POLICY_NAME: &str = "TopicData";
const TRANSPORTPRIORITY_QOS_POLICY_NAME: &str = "TransportPriority";
const GROUPDATA_QOS_POLICY_NAME: &str = "GroupData";
const LIFESPAN_QOS_POLICY_NAME: &str = "Lifespan";

pub const INVALID_QOS_POLICY_ID: QosPolicyId = 0;
pub const USERDATA_QOS_POLICY_ID: QosPolicyId = 1;
pub const DURABILITY_QOS_POLICY_ID: QosPolicyId = 2;
pub const PRESENTATION_QOS_POLICY_ID: QosPolicyId = 3;
pub const DEADLINE_QOS_POLICY_ID: QosPolicyId = 4;
pub const LATENCYBUDGET_QOS_POLICY_ID: QosPolicyId = 5;
pub const OWNERSHIP_QOS_POLICY_ID: QosPolicyId = 6;
pub const LIVELINESS_QOS_POLICY_ID: QosPolicyId = 8;
pub const TIMEBASEDFILTER_QOS_POLICY_ID: QosPolicyId = 9;
pub const PARTITION_QOS_POLICY_ID: QosPolicyId = 10;
pub const RELIABILITY_QOS_POLICY_ID: QosPolicyId = 11;
pub const DESTINATIONORDER_QOS_POLICY_ID: QosPolicyId = 12;
pub const HISTORY_QOS_POLICY_ID: QosPolicyId = 13;
pub const RESOURCELIMITS_QOS_POLICY_ID: QosPolicyId = 14;
pub const ENTITYFACTORY_QOS_POLICY_ID: QosPolicyId = 15;
pub const WRITERDATALIFECYCLE_QOS_POLICY_ID: QosPolicyId = 16;
pub const READERDATALIFECYCLE_QOS_POLICY_ID: QosPolicyId = 17;
pub const TOPICDATA_QOS_POLICY_ID: QosPolicyId = 18;
pub const GROUPDATA_QOS_POLICY_ID: QosPolicyId = 19;
pub const TRANSPORTPRIORITY_QOS_POLICY_ID: QosPolicyId = 20;
pub const LIFESPAN_QOS_POLICY_ID: QosPolicyId = 21;
pub const DURABILITYSERVICE_QOS_POLICY_ID: QosPolicyId = 22;

/// This policy allows the application to attach additional information to the created Entity objects such that when
/// a remote application discovers their existence it can access that information and use it for its own purposes.
#[derive(Debug, Default, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct UserDataQosPolicy {
    pub value: Vec<u8>,
}

impl QosPolicy for UserDataQosPolicy {
    fn name(&self) -> &str {
        USERDATA_QOS_POLICY_NAME
    }
}

/// This policy allows the application to attach additional information to the created Topic such that when a
/// remote application discovers their existence it can examine the information and use it in an application-defined way.
#[derive(Debug, Default, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct TopicDataQosPolicy {
    pub value: Vec<u8>,
}

impl QosPolicy for TopicDataQosPolicy {
    fn name(&self) -> &str {
        TOPICDATA_QOS_POLICY_NAME
    }
}

/// This policy allows the application to attach additional information to the created
/// [`Publisher`](crate::publication::publisher::Publisher) or [`Subscriber`](crate::subscription::subscriber::Subscriber).
///
/// The value is available to the application on the
/// [`DataReader`](crate::subscription::data_reader::DataReader) and [`DataWriter`](crate::publication::data_writer::DataWriter) entities and is propagated by
/// means of the built-in topics.
#[derive(Debug, Default, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct GroupDataQosPolicy {
    pub value: Vec<u8>,
}

impl QosPolicy for GroupDataQosPolicy {
    fn name(&self) -> &str {
        GROUPDATA_QOS_POLICY_NAME
    }
}

/// This policy allows the application to take advantage of transports capable of sending messages with different priorities.
///
/// This policy is considered a hint. The policy depends on the ability of the underlying transports to set a priority on the messages
/// they send. Any value within the range of a 32-bit signed integer may be chosen; higher values indicate higher priority.
/// However, any further interpretation of this policy is specific to a particular transport and a particular implementation of the
/// Service. For example, a particular transport is permitted to treat a range of priority values as equivalent to one another. It is
/// expected that during transport configuration the application would provide a mapping between the values of the
/// [`TransportPriorityQosPolicy`] set on [`DataWriter`](crate::publication::data_writer::DataWriter) and the values meaningful to each transport.
/// This mapping would then be used by the infrastructure when propagating the data written by the [`DataWriter`](crate::publication::data_writer::DataWriter).
#[derive(Debug, Default, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct TransportPriorityQosPolicy {
    pub value: i32,
}

impl QosPolicy for TransportPriorityQosPolicy {
    fn name(&self) -> &str {
        TRANSPORTPRIORITY_QOS_POLICY_NAME
    }
}

/// This policy is used to avoid delivering “stale” data to the application.
///
/// Each data sample written by the [`DataWriter`](crate::publication::data_writer::DataWriter) has an associated ‘expiration time’ beyond which the data should not be delivered
/// to any application. Once the sample expires, the data will be removed from the [`DataReader`](crate::subscription::data_reader::DataReader) caches as well as from the
/// transient and persistent information caches.
/// The ‘expiration time’ of each sample is computed by adding the duration specified by the [`LifespanQosPolicy`] to the source
/// timestamp. The source timestamp is either automatically computed by the Service
/// each time the [`DataWriter::write()`](crate::publication::data_writer::DataWriter) operation is called, or else supplied by the application by means
/// of the  [`DataWriter::write_w_timestamp()`](crate::publication::data_writer::DataWriter)
/// operation.
/// This QoS relies on the sender and receiving applications having their clocks sufficiently synchronized. If this is not the case
/// and the Service can detect it, the [`DataReader`](crate::subscription::data_reader::DataReader) is allowed to use the reception timestamp instead of the source timestamp in its
/// computation of the ‘expiration time.’
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct LifespanQosPolicy {
    pub duration: DurationKind,
}

impl QosPolicy for LifespanQosPolicy {
    fn name(&self) -> &str {
        LIFESPAN_QOS_POLICY_NAME
    }
}

impl Default for LifespanQosPolicy {
    fn default() -> Self {
        Self {
            duration: DurationKind::Infinite,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub enum DurabilityQosPolicyKind {
    Volatile,
    TransientLocal,
}

impl PartialOrd for DurabilityQosPolicyKind {
    fn partial_cmp(&self, other: &DurabilityQosPolicyKind) -> Option<Ordering> {
        match self {
            DurabilityQosPolicyKind::Volatile => match other {
                DurabilityQosPolicyKind::Volatile => Some(Ordering::Equal),
                DurabilityQosPolicyKind::TransientLocal => Some(Ordering::Less),
            },
            DurabilityQosPolicyKind::TransientLocal => match other {
                DurabilityQosPolicyKind::Volatile => Some(Ordering::Greater),
                DurabilityQosPolicyKind::TransientLocal => Some(Ordering::Equal),
            },
        }
    }
}

/// This policy controls whether the Service will actually make data available to late-joining readers.
///
/// The decoupling between [`DataReader`](crate::subscription::data_reader::DataReader) and [`DataWriter`](crate::publication::data_writer::DataWriter)
/// offered by the Publish/Subscribe paradigm allows an application to write data even if there are
/// no current readers on the network. Moreover, a [`DataReader`](crate::subscription::data_reader::DataReader) that joins the network after some data
/// has been written could potentially be interested in accessing the most current values of the data as well as potentially some
/// history.
/// Note that although related, this does not strictly control what data the Service will maintain internally.
/// That is, the Service may choose to maintain some data for its own purposes (e.g., flow control)
/// and yet not make it available to late-joining readers if the [`DurabilityQosPolicy`] is set to [`DurabilityQosPolicyKind::Volatile`].
/// The value offered is considered compatible with the value requested if and only if the *offered kind >= requested
/// kind* is true. For the purposes of this inequality, the values of [`DurabilityQosPolicyKind`] kind are considered ordered such
/// that *Volatile < TransientLocal*.
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
pub struct DurabilityQosPolicy {
    pub kind: DurabilityQosPolicyKind,
}

impl QosPolicy for DurabilityQosPolicy {
    fn name(&self) -> &str {
        DURABILITY_QOS_POLICY_NAME
    }
}

impl Default for DurabilityQosPolicy {
    fn default() -> Self {
        Self {
            kind: DurabilityQosPolicyKind::Volatile,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub enum PresentationQosPolicyAccessScopeKind {
    Instance,
    Topic,
}

impl PartialOrd for PresentationQosPolicyAccessScopeKind {
    fn partial_cmp(&self, other: &PresentationQosPolicyAccessScopeKind) -> Option<Ordering> {
        match self {
            PresentationQosPolicyAccessScopeKind::Instance => match other {
                PresentationQosPolicyAccessScopeKind::Instance => Some(Ordering::Equal),
                PresentationQosPolicyAccessScopeKind::Topic => Some(Ordering::Less),
            },
            PresentationQosPolicyAccessScopeKind::Topic => match other {
                PresentationQosPolicyAccessScopeKind::Instance => Some(Ordering::Greater),
                PresentationQosPolicyAccessScopeKind::Topic => Some(Ordering::Equal),
            },
        }
    }
}

/// This policy controls the extent to which changes to data-instances can be made dependent on each other and also the kind
/// of dependencies that can be propagated and maintained by the Service.
///
/// The setting of [`PresentationQosPolicy::coherent_access`] controls whether the Service will preserve the groupings of changes made by the publishing
/// application by means of the operations `begin_coherent_change()` and `end_coherent_change()`.
/// The setting of  [`PresentationQosPolicy::ordered_access`] controls whether the Service will preserve the order of changes.
/// The granularity is controlled by the setting of the  [`PresentationQosPolicy::access_scope`].
/// If [`PresentationQosPolicy::coherent_access`] is set, then the [`PresentationQosPolicy::access_scope`] controls the maximum extent of coherent changes.
/// The behavior is as follows:
/// - If access_scope is set to INSTANCE, the use of begin_coherent_change and end_coherent_change has no effect on
/// how the subscriber can access the data because with the scope limited to each instance, changes to separate instances
/// are considered independent and thus cannot be grouped by a coherent change.
/// - If access_scope is set to TOPIC, then coherent changes (indicated by their enclosure within calls to
/// begin_coherent_change and end_coherent_change) will be made available as such to each remote DataReader
/// independently. That is, changes made to instances within each individual DataWriter will be available as coherent with
/// respect to other changes to instances in that same DataWriter, but will not be grouped with changes made to instances
/// belonging to a different DataWriter.
/// If ordered_access is set, then the access_scope controls the maximum extent for which order will be preserved by the Service.
/// - If access_scope is set to INSTANCE (the lowest level), then changes to each instance are considered unordered relative
/// to changes to any other instance. That means that changes (creations, deletions, modifications) made to two instances
/// are not necessarily seen in the order they occur. This is the case even if it is the same application thread making the
/// changes using the same DataWriter.
/// - If access_scope is set to TOPIC, changes (creations, deletions, modifications) made by a single DataWriter are made
/// available to subscribers in the same order they occur. Changes made to instances through different DataWriter entities
/// are not necessarily seen in the order they occur. This is the case, even if the changes are made by a single application
/// thread using DataWriter objects attached to the same Publisher.
/// Note that this QoS policy controls the scope at which related changes are made available to the subscriber. This means the
/// subscriber can access the changes in a coherent manner and in the proper order; however, it does not necessarily imply that the
/// Subscriber will indeed access the changes in the correct order. For that to occur, the application at the subscriber end must use
/// the proper logic in reading the DataReader objects.
/// The value offered is considered compatible with the value requested if and only if the following conditions are met:
/// 1. The inequality “offered access_scope >= requested access_scope” is true. For the purposes of this
/// inequality, the values of PRESENTATION access_scope are considered ordered such that INSTANCE < TOPIC <
/// GROUP.
/// 2. Requested coherent_access is FALSE, or else both offered and requested coherent_access are TRUE.
/// 3. Requested ordered_access is FALSE, or else both offered and requested ordered _access are TRUE.
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct PresentationQosPolicy {
    pub access_scope: PresentationQosPolicyAccessScopeKind,
    pub coherent_access: bool,
    pub ordered_access: bool,
}

impl QosPolicy for PresentationQosPolicy {
    fn name(&self) -> &str {
        PRESENTATION_QOS_POLICY_NAME
    }
}

impl Default for PresentationQosPolicy {
    fn default() -> Self {
        Self {
            access_scope: PresentationQosPolicyAccessScopeKind::Instance,
            coherent_access: false,
            ordered_access: false,
        }
    }
}

/// This policy is useful for cases where a [`Topic`](crate::topic_definition::topic::Topic) is expected to have each instance updated periodically. On the publishing side this
/// setting establishes a contract that the application must meet.
///
/// On the subscribing side the setting establishes a minimum
/// requirement for the remote publishers that are expected to supply the data values.
/// When the Service ‘matches’ a [`DataWriter`](crate::publication::data_writer::DataWriter) and a [`DataReader`](crate::subscription::data_reader::DataReader) it checks whether the settings are compatible (i.e., *offered
/// deadline period <= requested deadline period*) if they are not, the two entities are informed (via the listener or condition
/// mechanism) of the incompatibility of the QoS settings and communication will not occur.
/// Assuming that the reader and writer ends have compatible settings, the fulfillment of this contract is monitored by the Service
/// and the application is informed of any violations by means of the proper listener or condition.
/// The value offered is considered compatible with the value requested if and only if the *offered deadline period <=
/// requested deadline period* is true.
/// The setting of the [`DeadlineQosPolicy`] policy must be set consistently with that of the [`TimeBasedFilterQosPolicy`]. For these two policies
/// to be consistent the settings must be such that *deadline period >= minimum_separation*.
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
pub struct DeadlineQosPolicy {
    pub period: DurationKind,
}

impl QosPolicy for DeadlineQosPolicy {
    fn name(&self) -> &str {
        DEADLINE_QOS_POLICY_NAME
    }
}

impl Default for DeadlineQosPolicy {
    fn default() -> Self {
        Self {
            period: DurationKind::Infinite,
        }
    }
}

/// This policy provides a means for the application to indicate to the middleware the “urgency” of the data-communication.
///
/// By having a non-zero duration the Service can optimize its internal operation.
/// This policy is considered a hint. There is no specified mechanism as to how the service should take advantage of this hint.
/// The value offered is considered compatible with the value requested if and only if the *offered duration <=
/// requested duration* is true.
#[derive(PartialOrd, PartialEq, Eq, Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LatencyBudgetQosPolicy {
    pub duration: DurationKind,
}

impl QosPolicy for LatencyBudgetQosPolicy {
    fn name(&self) -> &str {
        LATENCYBUDGET_QOS_POLICY_NAME
    }
}

impl Default for LatencyBudgetQosPolicy {
    fn default() -> Self {
        Self {
            duration: DurationKind::Finite(DURATION_ZERO),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub enum OwnershipQosPolicyKind {
    Shared,
}

/// This policy controls whether the Service allows multiple [`DataWriter`](crate::publication::data_writer::DataWriter)
/// objects to update the same instance (identified by Topic + key) of a data-object.
///
/// Only [`OwnershipQosPolicyKind::Shared`] can be selected. This setting indicates that the Service does not enforce unique ownership for each instance.
/// In this case, multiple writers can update the same data-object instance. The subscriber to the Topic will be able to access modifications from all DataWriter
/// objects, subject to the settings of other QoS that may filter particular samples (e.g., the [`TimeBasedFilterQosPolicy`] or [`HistoryQosPolicy`]).
/// In any case there is no “filtering” of modifications made based on the identity of the DataWriter that causes the
/// modification.

#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct OwnershipQosPolicy {
    pub kind: OwnershipQosPolicyKind,
}

impl QosPolicy for OwnershipQosPolicy {
    fn name(&self) -> &str {
        OWNERSHIP_QOS_POLICY_NAME
    }
}

impl Default for OwnershipQosPolicy {
    fn default() -> Self {
        Self {
            kind: OwnershipQosPolicyKind::Shared,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub enum LivelinessQosPolicyKind {
    Automatic,
    ManualByParticipant,
    ManualByTopic,
}

impl PartialOrd for LivelinessQosPolicyKind {
    fn partial_cmp(&self, other: &LivelinessQosPolicyKind) -> Option<Ordering> {
        match self {
            LivelinessQosPolicyKind::Automatic => match other {
                LivelinessQosPolicyKind::Automatic => Some(Ordering::Equal),
                LivelinessQosPolicyKind::ManualByParticipant => Some(Ordering::Less),
                LivelinessQosPolicyKind::ManualByTopic => Some(Ordering::Less),
            },
            LivelinessQosPolicyKind::ManualByParticipant => match other {
                LivelinessQosPolicyKind::Automatic => Some(Ordering::Greater),
                LivelinessQosPolicyKind::ManualByParticipant => Some(Ordering::Equal),
                LivelinessQosPolicyKind::ManualByTopic => Some(Ordering::Less),
            },
            LivelinessQosPolicyKind::ManualByTopic => match other {
                LivelinessQosPolicyKind::Automatic => Some(Ordering::Greater),
                LivelinessQosPolicyKind::ManualByParticipant => Some(Ordering::Greater),
                LivelinessQosPolicyKind::ManualByTopic => Some(Ordering::Equal),
            },
        }
    }
}

/// This policy controls the mechanism and parameters used by the Service to ensure that particular entities on the network are
/// still “alive”.
///
/// The liveliness can also affect the ownership of a particular instance, as determined by the [`OwnershipQosPolicy`].
/// This policy has several settings to support both data-objects that are updated periodically as well as those that are changed
/// sporadically. It also allows customizing for different application requirements in terms of the kinds of failures that will be
/// detected by the liveliness mechanism.
/// The [`LivelinessQosPolicyKind::Automatic`] liveliness setting is most appropriate for applications that only need to detect failures at the process level,
/// but not application-logic failures within a process. The Service takes responsibility for renewing the leases at the
/// required rates and thus, as long as the local process where a [`DomainParticipant`](crate::domain::domain_participant::DomainParticipant) is running and the link connecting it to remote
/// participants remains connected, the entities within the [`DomainParticipant`](crate::domain::domain_participant::DomainParticipant) will be considered alive. This requires the lowest
/// overhead.
/// The manual settings ([`LivelinessQosPolicyKind::ManualByParticipant`], [`LivelinessQosPolicyKind::ManualByTopic`]), require the application on the publishing
/// side to periodically assert the liveliness before the lease expires to indicate the corresponding Entity is still alive. The action
/// can be explicit by calling the `assert_liveliness()` operations, or implicit by writing some data.
/// The two possible manual settings control the granularity at which the application must assert liveliness.
/// The setting [`LivelinessQosPolicyKind::ManualByParticipant`] requires only that one Entity within the publisher is asserted to be alive to
/// deduce all other Entity objects within the same [`DomainParticipant`](crate::domain::domain_participant::DomainParticipant) are also alive.
/// The setting [`LivelinessQosPolicyKind::ManualByTopic`] requires that at least one instance within the [`DataWriter`](crate::publication::data_writer::DataWriter) is asserted.
/// The value offered is considered compatible with the value requested if and only if the inequality *offered kind >= requested kind* is true. For the purposes of this inequality, the values
/// of [`LivelinessQosPolicyKind`] kind are considered ordered such that *Automatic < ManualByParticipant < ManualByTopic*.
/// and the inequality *offered lease_duration <= requested lease_duration* is true.
/// Changes in liveliness must be detected by the Service with a time-granularity greater or equal to the [`LivelinessQosPolicy::lease_duration`]. This
/// ensures that the value of the LivelinessChangedStatus is updated at least once during each [`LivelinessQosPolicy::lease_duration`] and the related
/// Listeners and WaitSets are notified within a [`LivelinessQosPolicy::lease_duration`] from the time the liveliness changed.
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
pub struct LivelinessQosPolicy {
    pub kind: LivelinessQosPolicyKind,
    pub lease_duration: DurationKind,
}

impl QosPolicy for LivelinessQosPolicy {
    fn name(&self) -> &str {
        LIVELINESS_QOS_POLICY_NAME
    }
}

impl Default for LivelinessQosPolicy {
    fn default() -> Self {
        Self {
            kind: LivelinessQosPolicyKind::Automatic,
            lease_duration: DurationKind::Infinite,
        }
    }
}

/// This policy allows a [`DataReader`](crate::subscription::data_reader::DataReader) to indicate that it does not necessarily want to
/// see all values of each instance published under the [`Topic`](crate::topic_definition::topic::Topic).
/// Rather, it wants to see at most one change every [`TimeBasedFilterQosPolicy::minimum_separation`] period.
///
/// The [`TimeBasedFilterQosPolicy`] applies to each instance separately, that is, the constraint is that the [`DataReader`](crate::subscription::data_reader::DataReader)
/// does not want to see more than one sample of each instance per [`TimeBasedFilterQosPolicy::minimum_separation`] period.
/// This setting allows a [`DataReader`](crate::subscription::data_reader::DataReader) to further decouple itself from the
/// [`DataWriter`](crate::publication::data_writer::DataWriter) objects. It can be used to protect applications
/// that are running on a heterogeneous network where some nodes are capable of generating data much faster than others can
/// consume it. It also accommodates the fact that for fast-changing data different subscribers may have different requirements as
/// to how frequently they need to be notified of the most current values.
/// The setting of a [`TimeBasedFilterQosPolicy`], that is, the selection of a  [`TimeBasedFilterQosPolicy::minimum_separation`] with a value greater
/// than zero is compatible with all settings of the [`HistoryQosPolicy`] and [`ReliabilityQosPolicy`].
/// The [`TimeBasedFilterQosPolicy`] specifies the samples that are of interest to the [`DataReader`](crate::subscription::data_reader::DataReader).
/// The [`HistoryQosPolicy`] and [`ReliabilityQosPolicy`] affect the behavior of the middleware with
/// respect to the samples that have been determined to be of interest to the [`DataReader`](crate::subscription::data_reader::DataReader),
/// that is, they apply after the [`TimeBasedFilterQosPolicy`] has been applied.
/// In the case where the reliability [`ReliabilityQosPolicyKind::Reliable`]  then in steady-state, defined as the situation where
/// the [`DataWriter`](crate::publication::data_writer::DataWriter) does not write new samples for a period “long” compared to
/// the [`TimeBasedFilterQosPolicy::minimum_separation`], the system should guarantee delivery the last sample to the [`DataReader`](crate::subscription::data_reader::DataReader).
/// The setting of the  [`TimeBasedFilterQosPolicy::minimum_separation`] minimum_separation must be consistent with the [`DeadlineQosPolicy::period`]. For these
/// two QoS policies to be consistent they must verify that *[`DeadlineQosPolicy::period`] >= [`TimeBasedFilterQosPolicy::minimum_separation`]*.
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct TimeBasedFilterQosPolicy {
    pub minimum_separation: DurationKind,
}

impl QosPolicy for TimeBasedFilterQosPolicy {
    fn name(&self) -> &str {
        TIMEBASEDFILTER_QOS_POLICY_NAME
    }
}

impl Default for TimeBasedFilterQosPolicy {
    fn default() -> Self {
        Self {
            minimum_separation: DurationKind::Finite(DURATION_ZERO),
        }
    }
}

/// This policy allows the introduction of a logical partition concept inside the ‘physical’ partition induced by a domain.
///
/// For a [`DataReader`](crate::subscription::data_reader::DataReader) to see the changes made to an instance by a [`DataWriter`](crate::publication::data_writer::DataWriter),
/// not only the [`Topic`](crate::topic_definition::topic::Topic) must match, but also they must share a common partition.
/// Each string in the list that defines this QoS policy defines a partition name. A partition name may
/// contain wildcards. Sharing a common partition means that one of the partition names matches.
/// Failure to match partitions is not considered an “incompatible” QoS and does not trigger any listeners nor conditions.
/// This policy is changeable. A change of this policy can potentially modify the “match” of existing [`DataReader`](crate::subscription::data_reader::DataReader)
/// and [`DataWriter`](crate::publication::data_writer::DataWriter) entities. It may establish new “matchs” that did not exist before, or break existing matchs.
/// Partition names can be regular expressions and include wildcards as defined by the POSIX fnmatch API (1003.2-1992
/// section B.6). Either [`Publisher`](crate::publication::publisher::Publisher) or [`Subscriber`](crate::subscription::subscriber::Subscriber)
/// may include regular expressions in partition names, but no two names that both
/// contain wildcards will ever be considered to match. This means that although regular expressions may be used both at
/// publisher as well as subscriber side, the service will not try to match two regular expressions (between publishers and
/// subscribers).
/// Partitions are different from creating Entity objects in different domains in several ways. First, entities belonging to different
/// domains are completely isolated from each other; there is no traffic, meta-traffic or any other way for an application or the
/// Service itself to see entities in a domain it does not belong to. Second, an Entity can only belong to one domain whereas an
/// Entity can be in multiple partitions. Finally, as far as the DDS Service is concerned, each unique data instance is identified by
/// the tuple (domainId, Topic, key). Therefore two Entity objects in different domains cannot refer to the same data instance. On
/// the other hand, the same data-instance can be made available (published) or requested (subscribed) on one or more partitions.
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct PartitionQosPolicy {
    pub name: String,
}

impl QosPolicy for PartitionQosPolicy {
    fn name(&self) -> &str {
        PARTITION_QOS_POLICY_NAME
    }
}

impl Default for PartitionQosPolicy {
    fn default() -> Self {
        Self {
            name: "".to_string(),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ReliabilityQosPolicyKind {
    BestEffort,
    Reliable,
}

const BEST_EFFORT: i32 = 1;
const RELIABLE: i32 = 2;

impl serde::Serialize for ReliabilityQosPolicyKind {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serde::Serialize::serialize(
            &match self {
                ReliabilityQosPolicyKind::BestEffort => BEST_EFFORT,
                ReliabilityQosPolicyKind::Reliable => RELIABLE,
            },
            serializer,
        )
    }
}
struct ReliabilityQosPolicyKindVisitor;

impl<'de> serde::de::Visitor<'de> for ReliabilityQosPolicyKindVisitor {
    type Value = ReliabilityQosPolicyKind;

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        formatter.write_str(&format!("value `{:}` or `{:}`", BEST_EFFORT, RELIABLE))
    }

    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
    where
        E: serde::de::Error,
    {
        Ok(match value {
            BEST_EFFORT => ReliabilityQosPolicyKind::BestEffort,
            RELIABLE => ReliabilityQosPolicyKind::Reliable,
            _ => {
                return Err(serde::de::Error::invalid_value(
                    serde::de::Unexpected::Unsigned(value as u64),
                    &self,
                ))
            }
        })
    }
}

impl<'de> serde::Deserialize<'de> for ReliabilityQosPolicyKind {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_i32(ReliabilityQosPolicyKindVisitor)
    }
}

impl PartialOrd for ReliabilityQosPolicyKind {
    fn partial_cmp(&self, other: &ReliabilityQosPolicyKind) -> Option<Ordering> {
        match self {
            ReliabilityQosPolicyKind::BestEffort => match other {
                ReliabilityQosPolicyKind::BestEffort => Some(Ordering::Equal),
                ReliabilityQosPolicyKind::Reliable => Some(Ordering::Less),
            },
            ReliabilityQosPolicyKind::Reliable => match other {
                ReliabilityQosPolicyKind::BestEffort => Some(Ordering::Greater),
                ReliabilityQosPolicyKind::Reliable => Some(Ordering::Equal),
            },
        }
    }
}

/// This policy indicates the level of reliability requested by a [`DataReader`](crate::subscription::data_reader::DataReader)
/// or offered by a [`DataWriter`](crate::publication::data_writer::DataWriter).
///
/// These levels are ordered, [`ReliabilityQosPolicyKind::BestEffort`] being lower than [`ReliabilityQosPolicyKind::Reliable`].
/// A [`DataWriter`](crate::publication::data_writer::DataWriter) offering a level is implicitly offering all levels below.
/// The setting of this policy has a dependency on the setting of the [`ResourceLimitsQosPolicy`] policy.
/// In case the [`ReliabilityQosPolicyKind`] kind is set to [`ReliabilityQosPolicyKind::Reliable`] the write operation
/// on the [`DataWriter`](crate::publication::data_writer::DataWriter) may block if the modification would cause data to be lost or else
/// cause one of the limits in specified in the [`ResourceLimitsQosPolicy`] to be exceeded. Under these circumstances, the
///  [`ReliabilityQosPolicy::max_blocking_time`] configures the maximum duration the write operation may block.
/// If the [`ReliabilityQosPolicyKind`] kind is set to [`ReliabilityQosPolicyKind::Reliable`], data-samples originating from a
/// single [`DataWriter`](crate::publication::data_writer::DataWriter) cannot be made available
/// to the [`DataReader`](crate::subscription::data_reader::DataReader) if there are previous data-samples that have not been received
/// yet due to a communication error. In other words, the service will repair the error and re-transmit data-samples as needed
/// in order to re-construct a correct snapshot of the [`DataWriter`](crate::publication::data_writer::DataWriter) history before
/// it is accessible by the [`DataReader`](crate::subscription::data_reader::DataReader).
/// If the [`ReliabilityQosPolicyKind`] is set to [`ReliabilityQosPolicyKind::BestEffort`], the service will not re-transmit missing data samples.
/// However for data samples originating from any one [`DataWriter`](crate::publication::data_writer::DataWriter) the service will ensure
/// they are stored in the [`DataReader`](crate::subscription::data_reader::DataReader) history in the same
/// order they originated in the [`DataWriter`](crate::publication::data_writer::DataWriter).
/// In other words, the [`DataReader`](crate::subscription::data_reader::DataReader) may miss some data samples but it will never see the
/// value of a data-object change from a newer value to an older value.
/// The value offered is considered compatible with the value requested if and only if the inequality *offered kind >= requested
/// kind* is true. For the purposes of this inequality, the values of [`ReliabilityQosPolicyKind`] are considered ordered such
/// that *BestEffort < Reliable*.
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct ReliabilityQosPolicy {
    pub kind: ReliabilityQosPolicyKind,
    pub max_blocking_time: DurationKind,
}

impl QosPolicy for ReliabilityQosPolicy {
    fn name(&self) -> &str {
        RELIABILITY_QOS_POLICY_NAME
    }
}

impl PartialOrd for ReliabilityQosPolicy {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.kind.partial_cmp(&other.kind)
    }
}

// default for Reliability is differnet for reader and writer, hence
// add here as constants
const DEFAULT_MAX_BLOCKING_TIME: Duration = Duration::new(0, 100);
pub const DEFAULT_RELIABILITY_QOS_POLICY_DATA_READER_AND_TOPICS: ReliabilityQosPolicy =
    ReliabilityQosPolicy {
        kind: ReliabilityQosPolicyKind::BestEffort,
        max_blocking_time: DurationKind::Finite(DEFAULT_MAX_BLOCKING_TIME),
    };
pub const DEFAULT_RELIABILITY_QOS_POLICY_DATA_WRITER: ReliabilityQosPolicy = ReliabilityQosPolicy {
    kind: ReliabilityQosPolicyKind::Reliable,
    max_blocking_time: DurationKind::Finite(DEFAULT_MAX_BLOCKING_TIME),
};

#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub enum DestinationOrderQosPolicyKind {
    ByReceptionTimestamp,
    BySourceTimestamp,
}

impl PartialOrd for DestinationOrderQosPolicyKind {
    fn partial_cmp(&self, other: &DestinationOrderQosPolicyKind) -> Option<Ordering> {
        match self {
            DestinationOrderQosPolicyKind::ByReceptionTimestamp => match other {
                DestinationOrderQosPolicyKind::ByReceptionTimestamp => Some(Ordering::Equal),
                DestinationOrderQosPolicyKind::BySourceTimestamp => Some(Ordering::Less),
            },
            DestinationOrderQosPolicyKind::BySourceTimestamp => match other {
                DestinationOrderQosPolicyKind::ByReceptionTimestamp => Some(Ordering::Greater),
                DestinationOrderQosPolicyKind::BySourceTimestamp => Some(Ordering::Equal),
            },
        }
    }
}

/// This policy controls how each subscriber resolves the final value of a data instance that is written by multiple [`DataWriter`](crate::publication::data_writer::DataWriter)
/// objects (which may be associated with different [`Publisher`](crate::publication::publisher::Publisher) objects) running on different nodes.
///
/// The setting [`DestinationOrderQosPolicyKind::ByReceptionTimestamp`] indicates that, assuming the [`OwnershipQosPolicy`] policy allows it, the latest received
/// value for the instance should be the one whose value is kept. This is the default value.
/// The setting [`DestinationOrderQosPolicyKind::BySourceTimestamp`] indicates that, assuming the [`OwnershipQosPolicy`] policy allows it, a timestamp placed at
/// the source should be used. This is the only setting that, in the case of concurrent same-strength [`DataWriter`](crate::publication::data_writer::DataWriter) objects updating the
/// same instance, ensures all subscribers will end up with the same final value for the instance. The mechanism to set the source
/// timestamp is middleware dependent.
/// The value offered is considered compatible with the value requested if and only if the inequality *offered kind >= requested
/// kind* is true. For the purposes of this inequality, the values of [`DestinationOrderQosPolicyKind`] kind are considered
/// ordered such that *DestinationOrderQosPolicyKind::ByReceptionTimestamp < DestinationOrderQosPolicyKind::BySourceTimestamp*.
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
pub struct DestinationOrderQosPolicy {
    pub kind: DestinationOrderQosPolicyKind,
}

impl QosPolicy for DestinationOrderQosPolicyKind {
    fn name(&self) -> &str {
        DESTINATIONORDER_QOS_POLICY_NAME
    }
}

impl Default for DestinationOrderQosPolicy {
    fn default() -> Self {
        Self {
            kind: DestinationOrderQosPolicyKind::ByReceptionTimestamp,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub enum HistoryQosPolicyKind {
    KeepLast(i32),
    KeepAll,
}

/// This policy controls the behavior of the Service when the value of an instance changes before it is finally
/// communicated to some of its existing [`DataReader`](crate::subscription::data_reader::DataReader) entities.
///
/// If the kind is set to [`HistoryQosPolicyKind::KeepLast`], then the Service will only attempt to keep the latest values of the instance and
/// discard the older ones. In this case, the value of depth regulates the maximum number of values (up to and including
/// the most current one) the Service will maintain and deliver. The default (and most common setting) for depth is one,
/// indicating that only the most recent value should be delivered.
/// If the kind is set to [`HistoryQosPolicyKind::KeepAll`], then the Service will attempt to maintain and deliver all the values of the instance to
/// existing subscribers. The resources that the Service can use to keep this history are limited by the settings of the
/// [`ResourceLimitsQosPolicy`]. If the limit is reached, then the behavior of the Service will depend on the
/// [`ReliabilityQosPolicy`]. If the reliability kind is [`ReliabilityQosPolicyKind::BestEffort`], then the old values will be discarded. If reliability is
/// [`ReliabilityQosPolicyKind::Reliable`], then the Service will block the [`DataWriter`](crate::publication::data_writer::DataWriter) until it can deliver the necessary old values to all subscribers.
/// The setting of [`HistoryQosPolicy`] depth must be consistent with the [`ResourceLimitsQosPolicy::max_samples_per_instance`]. For these two
/// QoS to be consistent, they must verify that *depth <= max_samples_per_instance*.
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct HistoryQosPolicy {
    pub kind: HistoryQosPolicyKind,
}

impl QosPolicy for HistoryQosPolicy {
    fn name(&self) -> &str {
        HISTORY_QOS_POLICY_NAME
    }
}

impl Default for HistoryQosPolicy {
    fn default() -> Self {
        Self {
            kind: HistoryQosPolicyKind::KeepLast(1),
        }
    }
}

/// This policy controls the resources that the Service can use in order to meet the requirements imposed by the application and
/// other QoS settings.
///
/// If the [`DataWriter`](crate::publication::data_writer::DataWriter) objects are communicating samples faster than they are ultimately
/// taken by the [`DataReader`](crate::subscription::data_reader::DataReader) objects, the
/// middleware will eventually hit against some of the QoS-imposed resource limits. Note that this may occur when just a single
/// [`DataReader`](crate::subscription::data_reader::DataReader) cannot keep up with its corresponding [`DataWriter`](crate::publication::data_writer::DataWriter).
/// The behavior in this case depends on the setting for the [`ReliabilityQosPolicy`].
/// If reliability is [`ReliabilityQosPolicyKind::BestEffort`] then the Service is allowed to drop samples. If the reliability is
/// [`ReliabilityQosPolicyKind::Reliable`], the Service will block the DataWriter or discard the sample at the
/// [`DataReader`](crate::subscription::data_reader::DataReader) in order not to lose existing samples.
/// The constant [`Length::Unlimited`] may be used to indicate the absence of a particular limit. For example setting
/// [`ResourceLimitsQosPolicy::max_samples_per_instance`] to [`Length::Unlimited`] will cause the middleware to not enforce
/// this particular limit.
/// The setting of [`ResourceLimitsQosPolicy::max_samples`] must be consistent with the [`ResourceLimitsQosPolicy::max_samples_per_instance`].
/// For these two values to be consistent they must verify that *max_samples >= max_samples_per_instance*.
/// The setting of [`ResourceLimitsQosPolicy::max_samples_per_instance`] must be consistent with the
/// [`HistoryQosPolicy`] depth. For these two QoS to be consistent, they must verify
/// that *HistoryQosPolicy depth <= [`ResourceLimitsQosPolicy::max_samples_per_instance`]*.
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct ResourceLimitsQosPolicy {
    pub max_samples: Length,
    pub max_instances: Length,
    pub max_samples_per_instance: Length,
}

impl QosPolicy for ResourceLimitsQosPolicy {
    fn name(&self) -> &str {
        RESOURCELIMITS_QOS_POLICY_NAME
    }
}

impl Default for ResourceLimitsQosPolicy {
    fn default() -> Self {
        Self {
            max_samples: Length::Unlimited,
            max_instances: Length::Unlimited,
            max_samples_per_instance: Length::Unlimited,
        }
    }
}

/// This policy controls the behavior of the Entity as a factory for other entities.
///
/// This policy concerns only DomainParticipant (as factory for Publisher, Subscriber, and Topic), Publisher (as factory for
/// DataWriter), and Subscriber (as factory for DataReader).
/// This policy is mutable. A change in the policy affects only the entities created after the change; not the previously created
/// entities.
/// The setting of `autoenable_created_entities` to [`true`] indicates that the factory `create_<entity>` operation will automatically
/// invoke the enable operation each time a new Entity is created. Therefore, the Entity returned by `create_...` will already
/// be enabled. A setting of [`false`] indicates that the Entity will not be automatically enabled. The application will need to enable
/// it explicitly by means of the `enable()` operation.
/// The default setting of `autoenable_created_entities` is [`true`] which means that, by default, it is not necessary to explicitly call `enable()`
/// on newly created entities.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct EntityFactoryQosPolicy {
    pub autoenable_created_entities: bool,
}

impl QosPolicy for EntityFactoryQosPolicy {
    fn name(&self) -> &str {
        ENTITYFACTORY_QOS_POLICY_NAME
    }
}

impl Default for EntityFactoryQosPolicy {
    fn default() -> Self {
        Self {
            autoenable_created_entities: true,
        }
    }
}

/// This policy controls the behavior of the [`DataWriter`](crate::publication::data_writer::DataWriter) with regards to the lifecycle
/// of the data-instances it manages, that is, the data-instances that have been either explicitly registered with the
/// [`DataWriter::register`](crate::publication::data_writer::DataWriter) or implicitly by using [`DataWriter::write`](crate::publication::data_writer::DataWriter)
///
/// The [`WriterDataLifecycleQosPolicy::autodispose_unregistered_instances`] flag controls the behavior when the
/// DataWriter unregisters an instance by means of the [`DataWriter::unregister_instance`](crate::publication::data_writer::DataWriter) operations:
/// - The setting [`WriterDataLifecycleQosPolicy::autodispose_unregistered_instances`] = [`true`] causes the [`DataWriter::unregister_instance`](crate::publication::data_writer::DataWriter)
///   to dispose the instance each time it is unregistered.
///   The behavior is identical to explicitly calling one of the [`DataWriter::dispose`](crate::publication::data_writer::DataWriter) operations on the
///   instance prior to calling the unregister operation.
/// - The setting [`WriterDataLifecycleQosPolicy::autodispose_unregistered_instances`] = [`false`]  will not cause this automatic disposition upon unregistering.
///   The application can still call one of the dispose operations prior to unregistering the instance and accomplish the same effect.
///
/// Note that the deletion of a [`DataWriter`](crate::publication::data_writer::DataWriter) automatically unregisters all data-instances it manages.
/// Therefore the setting of the [`WriterDataLifecycleQosPolicy::autodispose_unregistered_instances`] flag will determine whether instances are ultimately disposed when the
/// [`DataWriter`](crate::publication::data_writer::DataWriter) is deleted.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct WriterDataLifecycleQosPolicy {
    pub autodispose_unregistered_instances: bool,
}

impl QosPolicy for WriterDataLifecycleQosPolicy {
    fn name(&self) -> &str {
        WRITERDATALIFECYCLE_QOS_POLICY_NAME
    }
}

impl Default for WriterDataLifecycleQosPolicy {
    fn default() -> Self {
        Self {
            autodispose_unregistered_instances: true,
        }
    }
}

/// This policy controls the behavior of the [`DataReader`](crate::subscription::data_reader::DataReader) with regards to the lifecycle of the data-instances it manages, that is, the
/// data-instances that have been received and for which the [`DataReader`](crate::subscription::data_reader::DataReader) maintains some internal resources.
///
/// The [`DataReader`](crate::subscription::data_reader::DataReader) internally maintains the samples that have not been taken by the application, subject to the constraints
/// imposed by other QoS policies such as [`HistoryQosPolicy`] and [`ResourceLimitsQosPolicy`].
/// The [`DataReader`](crate::subscription::data_reader::DataReader) also maintains information regarding the identity, view_state and instance_state
/// of data-instances even after all samples have been ‘taken.’ This is needed to properly compute the states when future samples arrive.
/// Under normal circumstances the [`DataReader`](crate::subscription::data_reader::DataReader) can only reclaim all resources for instances for which there are no writers and for
/// which all samples have been ‘taken’. The last sample the [`DataReader`](crate::subscription::data_reader::DataReader) will have taken for that instance will have an
/// `instance_state` of either [`InstanceStateKind::NotAliveNoWriters`](crate::subscription::sample_info::InstanceStateKind) or
/// [`InstanceStateKind::NotAliveDisposed`](crate::subscription::sample_info::InstanceStateKind) depending on whether the last writer
/// that had ownership of the instance disposed it or not.  In the absence of the [`ReaderDataLifecycleQosPolicy`] this behavior could cause problems if the
/// application “forgets” to ‘take’ those samples. The ‘untaken’ samples will prevent the [`DataReader`](crate::subscription::data_reader::DataReader) from reclaiming the
/// resources and they would remain in the [`DataReader`](crate::subscription::data_reader::DataReader) indefinitely.
/// The [`ReaderDataLifecycleQosPolicy::autopurge_nowriter_samples_delay`] defines the maximum duration for which the [`DataReader`](crate::subscription::data_reader::DataReader) will maintain information
/// regarding an instance once its `instance_state` becomes [`InstanceStateKind::NotAliveNoWriters`](crate::subscription::sample_info::InstanceStateKind). After this time elapses, the [`DataReader`](crate::subscription::data_reader::DataReader)
/// will purge all internal information regarding the instance, any untaken samples will also be lost.
/// The [`ReaderDataLifecycleQosPolicy::autopurge_disposed_samples_delay`] defines the maximum duration for which the [`DataReader`](crate::subscription::data_reader::DataReader) will maintain samples for
/// an instance once its `instance_state` becomes [`InstanceStateKind::NotAliveDisposed`](crate::subscription::sample_info::InstanceStateKind). After this time elapses, the [`DataReader`](crate::subscription::data_reader::DataReader) will purge all
/// samples for the instance.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ReaderDataLifecycleQosPolicy {
    pub autopurge_nowriter_samples_delay: DurationKind,
    pub autopurge_disposed_samples_delay: DurationKind,
}

impl QosPolicy for ReaderDataLifecycleQosPolicy {
    fn name(&self) -> &str {
        READERDATALIFECYCLE_QOS_POLICY_NAME
    }
}

impl Default for ReaderDataLifecycleQosPolicy {
    fn default() -> Self {
        Self {
            autopurge_nowriter_samples_delay: DurationKind::Infinite,
            autopurge_disposed_samples_delay: DurationKind::Infinite,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn durability_qos_policy_kind_ordering() {
        assert!(DurabilityQosPolicyKind::Volatile < DurabilityQosPolicyKind::TransientLocal);

        assert!(DurabilityQosPolicyKind::Volatile == DurabilityQosPolicyKind::Volatile);
        assert!(DurabilityQosPolicyKind::Volatile < DurabilityQosPolicyKind::TransientLocal);

        assert!(DurabilityQosPolicyKind::TransientLocal > DurabilityQosPolicyKind::Volatile);
        assert!(DurabilityQosPolicyKind::TransientLocal == DurabilityQosPolicyKind::TransientLocal);
    }

    #[test]
    fn presentation_qos_policy_access_scope_kind_ordering() {
        assert!(
            PresentationQosPolicyAccessScopeKind::Instance
                < PresentationQosPolicyAccessScopeKind::Topic
        );

        assert!(
            PresentationQosPolicyAccessScopeKind::Instance
                == PresentationQosPolicyAccessScopeKind::Instance
        );
        assert!(
            PresentationQosPolicyAccessScopeKind::Instance
                < PresentationQosPolicyAccessScopeKind::Topic
        );

        assert!(
            PresentationQosPolicyAccessScopeKind::Topic
                > PresentationQosPolicyAccessScopeKind::Instance
        );
        assert!(
            PresentationQosPolicyAccessScopeKind::Topic
                == PresentationQosPolicyAccessScopeKind::Topic
        );
    }

    #[test]
    fn liveliness_qos_policy_kind_ordering() {
        assert!(LivelinessQosPolicyKind::Automatic < LivelinessQosPolicyKind::ManualByParticipant);
        assert!(
            LivelinessQosPolicyKind::ManualByParticipant < LivelinessQosPolicyKind::ManualByTopic
        );

        assert!(LivelinessQosPolicyKind::Automatic == LivelinessQosPolicyKind::Automatic);
        assert!(LivelinessQosPolicyKind::Automatic < LivelinessQosPolicyKind::ManualByParticipant);
        assert!(LivelinessQosPolicyKind::Automatic < LivelinessQosPolicyKind::ManualByTopic);

        assert!(LivelinessQosPolicyKind::ManualByParticipant > LivelinessQosPolicyKind::Automatic);
        assert!(
            LivelinessQosPolicyKind::ManualByParticipant
                == LivelinessQosPolicyKind::ManualByParticipant
        );
        assert!(
            LivelinessQosPolicyKind::ManualByParticipant < LivelinessQosPolicyKind::ManualByTopic
        );

        assert!(LivelinessQosPolicyKind::ManualByTopic > LivelinessQosPolicyKind::Automatic);
        assert!(
            LivelinessQosPolicyKind::ManualByTopic > LivelinessQosPolicyKind::ManualByParticipant
        );
        assert!(LivelinessQosPolicyKind::ManualByTopic == LivelinessQosPolicyKind::ManualByTopic);
    }

    #[test]
    fn reliability_qos_policy_kind_ordering() {
        assert!(ReliabilityQosPolicyKind::BestEffort < ReliabilityQosPolicyKind::Reliable);

        assert!(ReliabilityQosPolicyKind::BestEffort == ReliabilityQosPolicyKind::BestEffort);
        assert!(ReliabilityQosPolicyKind::BestEffort < ReliabilityQosPolicyKind::Reliable);

        assert!(ReliabilityQosPolicyKind::Reliable > ReliabilityQosPolicyKind::BestEffort);
        assert!(ReliabilityQosPolicyKind::Reliable == ReliabilityQosPolicyKind::Reliable);
    }

    #[test]
    fn destination_order_qos_policy_kind_ordering() {
        assert!(
            DestinationOrderQosPolicyKind::ByReceptionTimestamp
                < DestinationOrderQosPolicyKind::BySourceTimestamp
        );

        assert!(
            DestinationOrderQosPolicyKind::ByReceptionTimestamp
                == DestinationOrderQosPolicyKind::ByReceptionTimestamp
        );
        assert!(
            DestinationOrderQosPolicyKind::ByReceptionTimestamp
                < DestinationOrderQosPolicyKind::BySourceTimestamp
        );

        assert!(
            DestinationOrderQosPolicyKind::BySourceTimestamp
                > DestinationOrderQosPolicyKind::ByReceptionTimestamp
        );
        assert!(
            DestinationOrderQosPolicyKind::BySourceTimestamp
                == DestinationOrderQosPolicyKind::BySourceTimestamp
        );
    }

    #[test]
    fn length_ordering() {
        assert!(Length::Unlimited > Length::Limited(10));
        assert!(Length::Unlimited == Length::Unlimited);
        assert!(Length::Limited(10) < Length::Unlimited);
        assert!(Length::Limited(10) < Length::Limited(20));
        assert!(Length::Limited(20) > Length::Limited(10));
    }

    #[test]
    fn length_usize_ordering() {
        assert!(Length::Unlimited > 10usize);
        assert!(10usize < Length::Unlimited);
        assert!(Length::Limited(20) > 10usize);
        assert!(10usize < Length::Limited(20));
        assert!(Length::Limited(10) == 10usize);
        assert!(10usize == Length::Limited(10));
    }
}