dust_dds 0.15.0

Data Distribution Service (DDS) implementation
Documentation
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
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
use super::time::{DURATION_ZERO_NSEC, DURATION_ZERO_SEC};
use crate::{
    infrastructure::{
        time::{Duration, DurationKind},
        type_support::TypeSupport,
    },
    transport::types::{DurabilityKind, ReliabilityKind},
    xtypes::{
        binding::XTypesBinding,
        dynamic_type::{DynamicDataFactory, TypeKind},
    },
};
use alloc::{string::String, vec::Vec};
use core::cmp::Ordering;

/// QosPolicyId type alias
pub type QosPolicyId = i32;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
/// Enumeration representing a Length which be either limited or unlimited.
pub enum Length {
    /// Unlimited length.
    Unlimited,
    /// Limited length with the corresponding associated value.
    Limited(i32),
}

impl TypeSupport for Length {
    #[inline]
    fn get_type_name() -> &'static str {
        "Length"
    }

    #[inline]
    fn get_type() -> crate::xtypes::dynamic_type::DynamicType {
        i32::get_dynamic_type()
    }

    fn create_dynamic_sample(self) -> crate::xtypes::dynamic_type::DynamicData {
        let value = match self {
            Length::Limited(length) => length,
            Length::Unlimited => LENGTH_UNLIMITED,
        };
        let mut data = DynamicDataFactory::create_data(Self::get_type());
        data.set_int32_value(0, value).unwrap();
        data
    }

    fn create_sample(src: crate::xtypes::dynamic_type::DynamicData) -> Self {
        let value = src.get_int32_value(0).cloned().unwrap();
        match value {
            LENGTH_UNLIMITED => Length::Unlimited,
            v => Length::Limited(v),
        }
    }
}

const LENGTH_UNLIMITED: i32 = i32::MAX;

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 {
    /// Get the name of the QoS policy
    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 OWNERSHIP_STRENGTH_QOS_POLICY_NAME: &str = "OwnershipStrength";
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";
const DATA_REPRESENTATION_QOS_POLICY_NAME: &str = "DataRepresentation";

/// QosPolicy Id representing an invalid QoS policy
pub const INVALID_QOS_POLICY_ID: QosPolicyId = 0;
/// Id for the UserDataQosPolicy
pub const USERDATA_QOS_POLICY_ID: QosPolicyId = 1;
/// Id for the DurabilityQosPolicy
pub const DURABILITY_QOS_POLICY_ID: QosPolicyId = 2;
/// Id for the PresentationQosPolicy
pub const PRESENTATION_QOS_POLICY_ID: QosPolicyId = 3;
/// Id for the DeadlineQosPolicy
pub const DEADLINE_QOS_POLICY_ID: QosPolicyId = 4;
/// Id for the LatencyBudgetQosPolicy
pub const LATENCYBUDGET_QOS_POLICY_ID: QosPolicyId = 5;
/// Id for the OwnershipQosPolicy
pub const OWNERSHIP_QOS_POLICY_ID: QosPolicyId = 6;
/// Id for the OwnershipStrengthQosPolicy
pub const OWNERSHIP_STRENGTH_QOS_POLICY_ID: QosPolicyId = 7;
/// Id for the LivelinessQosPolicy
pub const LIVELINESS_QOS_POLICY_ID: QosPolicyId = 8;
/// Id for the TimeBasedFilterQosPolicy
pub const TIMEBASEDFILTER_QOS_POLICY_ID: QosPolicyId = 9;
/// Id for the PartitionQosPolicy
pub const PARTITION_QOS_POLICY_ID: QosPolicyId = 10;
/// Id for the ReliabilityQosPolicy
pub const RELIABILITY_QOS_POLICY_ID: QosPolicyId = 11;
/// Id for the DestinationOrderQosPolicy
pub const DESTINATIONORDER_QOS_POLICY_ID: QosPolicyId = 12;
/// Id for the HistoryQosPolicy
pub const HISTORY_QOS_POLICY_ID: QosPolicyId = 13;
/// Id for the ResourceLimitsQosPolicy
pub const RESOURCELIMITS_QOS_POLICY_ID: QosPolicyId = 14;
/// Id for the EntityFactoryQosPolicy
pub const ENTITYFACTORY_QOS_POLICY_ID: QosPolicyId = 15;
/// Id for the WriterDataLifecycleQosPolicy
pub const WRITERDATALIFECYCLE_QOS_POLICY_ID: QosPolicyId = 16;
/// Id for the ReaderDataLifecycleQosPolicy
pub const READERDATALIFECYCLE_QOS_POLICY_ID: QosPolicyId = 17;
/// Id for the TopicDataQosPolicy
pub const TOPICDATA_QOS_POLICY_ID: QosPolicyId = 18;
/// Id for the GroupDataQosPolicy
pub const GROUPDATA_QOS_POLICY_ID: QosPolicyId = 19;
/// Id for the TransportPriorityQosPolicy
pub const TRANSPORTPRIORITY_QOS_POLICY_ID: QosPolicyId = 20;
/// Id for the LifespanQosPolicy
pub const LIFESPAN_QOS_POLICY_ID: QosPolicyId = 21;
/// Id for the DurabilityServiceQosPolicy
pub const DURABILITYSERVICE_QOS_POLICY_ID: QosPolicyId = 22;
/// Id for the DataRepresentationQosPolicy
pub const DATA_REPRESENTATION_QOS_POLICY_ID: QosPolicyId = 23;

/// 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, PartialEq, Eq, Clone, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct UserDataQosPolicy {
    /// User data value
    pub value: Vec<u8>,
}

impl UserDataQosPolicy {
    pub const fn const_default() -> Self {
        Self { value: Vec::new() }
    }
}

impl QosPolicy for UserDataQosPolicy {
    fn name(&self) -> &str {
        USERDATA_QOS_POLICY_NAME
    }
}
impl Default for UserDataQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, PartialEq, Eq, Clone, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct TopicDataQosPolicy {
    /// Topic data value
    pub value: Vec<u8>,
}

impl TopicDataQosPolicy {
    pub const fn const_default() -> Self {
        Self { value: Vec::new() }
    }
}

impl Default for TopicDataQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

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, PartialEq, Eq, Clone, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct GroupDataQosPolicy {
    /// Group data value
    pub value: Vec<u8>,
}

impl GroupDataQosPolicy {
    pub const fn const_default() -> Self {
        Self { value: Vec::new() }
    }
}

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

impl Default for GroupDataQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, PartialEq, Eq, Clone, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct TransportPriorityQosPolicy {
    /// Transport priority value
    pub value: i32,
}

impl TransportPriorityQosPolicy {
    pub const fn const_default() -> Self {
        Self { value: 0 }
    }
}

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

impl Default for TransportPriorityQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct LifespanQosPolicy {
    /// Lifespan duration
    pub duration: DurationKind,
}

impl LifespanQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            duration: DurationKind::Infinite,
        }
    }
}

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

impl Default for LifespanQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, TypeSupport)]
/// Enumeration representing the different types of Durability QoS policies.
pub enum DurabilityQosPolicyKind {
    /// Volatile durability QoS policy
    Volatile,
    /// TransientLocal durability QoS policy
    TransientLocal,
    /// Transient durability QoS policy
    Transient,
    /// Persistent durability QoS policy
    Persistent,
}

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::Transient => Some(Ordering::Less),
                DurabilityQosPolicyKind::Persistent => Some(Ordering::Less),
            },
            DurabilityQosPolicyKind::TransientLocal => match other {
                DurabilityQosPolicyKind::Volatile => Some(Ordering::Greater),
                DurabilityQosPolicyKind::TransientLocal => Some(Ordering::Equal),
                DurabilityQosPolicyKind::Transient => Some(Ordering::Less),
                DurabilityQosPolicyKind::Persistent => Some(Ordering::Less),
            },
            DurabilityQosPolicyKind::Transient => match other {
                DurabilityQosPolicyKind::Volatile => Some(Ordering::Greater),
                DurabilityQosPolicyKind::TransientLocal => Some(Ordering::Greater),
                DurabilityQosPolicyKind::Transient => Some(Ordering::Equal),
                DurabilityQosPolicyKind::Persistent => Some(Ordering::Less),
            },
            DurabilityQosPolicyKind::Persistent => match other {
                DurabilityQosPolicyKind::Volatile => Some(Ordering::Greater),
                DurabilityQosPolicyKind::TransientLocal => Some(Ordering::Greater),
                DurabilityQosPolicyKind::Transient => Some(Ordering::Greater),
                DurabilityQosPolicyKind::Persistent => 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct DurabilityQosPolicy {
    /// DurabilityQosPolicy kind to be used for this policy
    pub kind: DurabilityQosPolicyKind,
}

impl DurabilityQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            kind: DurabilityQosPolicyKind::Volatile,
        }
    }
}

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

impl Default for DurabilityQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, TypeSupport)]
/// Enumeration representing the different types of Presentation QoS policy access scope.
pub enum PresentationQosPolicyAccessScopeKind {
    /// Access scope per instance
    Instance,
    /// Access scope per topic
    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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct PresentationQosPolicy {
    /// Presentation access scope kind to be used for this policy
    pub access_scope: PresentationQosPolicyAccessScopeKind,
    /// Coherent access value
    pub coherent_access: bool,
    /// Ordered access value
    pub ordered_access: bool,
}

impl PresentationQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            access_scope: PresentationQosPolicyAccessScopeKind::Instance,
            coherent_access: false,
            ordered_access: false,
        }
    }
}

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

impl Default for PresentationQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct DeadlineQosPolicy {
    /// Deadline period value
    pub period: DurationKind,
}

impl DeadlineQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            period: DurationKind::Infinite,
        }
    }
}

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

impl Default for DeadlineQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct LatencyBudgetQosPolicy {
    /// Latency budget duration value
    pub duration: DurationKind,
}

impl LatencyBudgetQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            duration: DurationKind::Finite(Duration::new(DURATION_ZERO_SEC, DURATION_ZERO_NSEC)),
        }
    }
}

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

impl Default for LatencyBudgetQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// Enumeration representing the different types of Ownership QoS policies.
#[derive(Debug, PartialEq, Eq, Clone, Copy, TypeSupport)]
pub enum OwnershipQosPolicyKind {
    /// Shared ownership QoS policy
    Shared,
    /// Exclusive ownership QoS policy
    Exclusive,
}

/// 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct OwnershipQosPolicy {
    /// Kind of ownership QoS associated with this policy
    pub kind: OwnershipQosPolicyKind,
}

impl OwnershipQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            kind: OwnershipQosPolicyKind::Shared,
        }
    }
}

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

impl Default for OwnershipQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// This policy should be used in combination with the [`OwnershipQosPolicy`]. It only applies to the case where
/// [`OwnershipQosPolicy`] kind is set to [`OwnershipQosPolicyKind::Exclusive`].
///
/// The value of the [`OwnershipStrengthQosPolicy`] is used to determine the ownership of a data-instance (identified by the key).
/// The arbitration is performed by the DataReader.
/// This setting indicates that each instance of a data-object can only be modified by one DataWriter. In other words, at any point
/// in time a single DataWriter "owns" each instance and is the only one whose modifications will be visible to the DataReader
/// objects. The owner is determined by selecting the DataWriter with the highest value of the strength that is both "alive" as
/// defined by the LIVELINESS QoS policy and has not violated its DEADLINE contract with regards to the data-instance.
/// Ownership can therefore change as a result of (a) a DataWriter in the system with a higher value of the strength that modifies
/// the instance, (b) a change in the strength value of the DataWriter that owns the instance, (c) a change in the liveliness of the
/// DataWriter that owns the instance, and (d) a deadline with regards to the instance that is missed by the DataWriter that owns
/// the instance.
/// The behavior of the system is as if the determination was made independently by each DataReader. Each DataReader may
/// detect the change of ownership at a different time. It is not a requirement that at a particular point in time all the DataReader
/// objects for that Topic have a consistent picture of who owns each instance.
/// It is also not a requirement that the DataWriter objects are aware of whether they own a particular instance. There is no error or
/// notification given to a DataWriter that modifies an instance it does not currently own.
/// The requirements are chosen to (a) preserve the decoupling of publishers and subscriber, and (b) allow the policy to be
/// implemented efficiently.
/// It is possible that multiple DataWriter objects with the same strength modify the same instance. If this occurs the Service will
/// pick one of the DataWriter objects as the "owner". It is not specified how the owner is selected. However, it is required that the
/// policy used to select the owner is such that all DataReader objects will make the same choice of the particular DataWriter that
/// is the owner. It is also required that the owner remains the same until there is a change in strength, liveliness, the owner misses
/// a deadline on the instance, a new DataWriter with higher strength modifies the instance, or another DataWriter with the same
/// strength that is deemed by the Service to be the new owner modifies the instance.
/// Exclusive ownership is on an instance-by-instance basis. That is, a subscriber can receive values written by a lower
/// strength DataWriter as long as they affect instances whose values have not been set by the higher-strength
/// DataWriter.
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct OwnershipStrengthQosPolicy {
    /// Ownership strength value
    pub value: i32,
}

impl OwnershipStrengthQosPolicy {
    pub const fn const_default() -> Self {
        Self { value: 0 }
    }
}

impl QosPolicy for OwnershipStrengthQosPolicy {
    fn name(&self) -> &str {
        OWNERSHIP_STRENGTH_QOS_POLICY_NAME
    }
}

impl Default for OwnershipStrengthQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// Enumeration representing the different types of Liveliness QoS policies.
#[derive(Debug, PartialEq, Eq, Clone, Copy, TypeSupport)]
pub enum LivelinessQosPolicyKind {
    /// Automatic liveliness
    Automatic,
    /// Manual by participant liveliness
    ManualByParticipant,
    /// Manual by topic liveliness
    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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct LivelinessQosPolicy {
    /// Kind of liveliness QoS associated with this policy
    pub kind: LivelinessQosPolicyKind,
    /// Liveliness duration
    pub lease_duration: DurationKind,
}

impl LivelinessQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            kind: LivelinessQosPolicyKind::Automatic,
            lease_duration: DurationKind::Infinite,
        }
    }
}

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

impl Default for LivelinessQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct TimeBasedFilterQosPolicy {
    /// Minimum separation between samples
    pub minimum_separation: DurationKind,
}

impl TimeBasedFilterQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            minimum_separation: DurationKind::Finite(Duration::new(
                DURATION_ZERO_SEC,
                DURATION_ZERO_NSEC,
            )),
        }
    }
}

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

impl Default for TimeBasedFilterQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct PartitionQosPolicy {
    /// Name of the partition
    pub name: Vec<String>,
}

impl PartitionQosPolicy {
    pub const fn const_default() -> Self {
        Self { name: Vec::new() }
    }
}

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

impl Default for PartitionQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// Enumeration representing the different types of reliability QoS policies.
#[derive(Debug, PartialEq, Eq, Clone, Copy, TypeSupport)]
#[repr(i32)]
pub enum ReliabilityQosPolicyKind {
    /// Best-effort reliability.
    BestEffort = 1,
    /// Reliable reliability.
    Reliable = 2,
}

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

// impl dust_dds::infrastructure::type_support::TypeSupport for ReliabilityQosPolicyKind {
//     fn get_type() -> dust_dds::xtypes::dynamic_type::DynamicType {
//         extern crate alloc;
//         let builder = dust_dds::xtypes::dynamic_type::DynamicTypeBuilderFactory::create_type(
//             dust_dds::xtypes::dynamic_type::TypeDescriptor {
//                 kind: dust_dds::xtypes::dynamic_type::TypeKind::ENUM,
//                 name: alloc::string::String::from("ReliabilityQosPolicyKind"),
//                 base_type: None,
//                 discriminator_type: Some(
//                     dust_dds::xtypes::dynamic_type::DynamicTypeBuilderFactory::get_primitive_type(
//                         dust_dds::xtypes::dynamic_type::TypeKind::INT32,
//                     ),
//                 ),
//                 bound: alloc::vec::Vec::new(),
//                 element_type: None,
//                 key_element_type: None,
//                 extensibility_kind: dust_dds::xtypes::dynamic_type::ExtensibilityKind::Final,
//                 is_nested: false,
//             },
//         );
//         builder.build()
//     }

//     fn create_sample(src: crate::xtypes::dynamic_type::DynamicData) -> Self {
//         let discriminator = src.get_int32_value(0).ex
//     }

//     fn create_dynamic_sample(self) -> dust_dds::xtypes::dynamic_type::DynamicData {
//         let mut data =
//             dust_dds::xtypes::dynamic_type::DynamicDataFactory::create_data(Self::get_type());
//         data.set_int32_value(0, self as i32).unwrap();
//         data
//     }
// }

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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct ReliabilityQosPolicy {
    /// Kind of reliability QoS
    pub kind: ReliabilityQosPolicyKind,
    /// Maximum blocking time to block. This only applies when kind is set to [`ReliabilityQosPolicyKind::Reliable`]
    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 different for reader and writer, hence
// added here as constants
const DEFAULT_MAX_BLOCKING_TIME: Duration = Duration::new(0, 100_000_000);
pub(crate) const DEFAULT_RELIABILITY_QOS_POLICY_DATA_READER_AND_TOPICS: ReliabilityQosPolicy =
    ReliabilityQosPolicy {
        kind: ReliabilityQosPolicyKind::BestEffort,
        max_blocking_time: DurationKind::Finite(DEFAULT_MAX_BLOCKING_TIME),
    };
pub(crate) const DEFAULT_RELIABILITY_QOS_POLICY_DATA_WRITER: ReliabilityQosPolicy =
    ReliabilityQosPolicy {
        kind: ReliabilityQosPolicyKind::Reliable,
        max_blocking_time: DurationKind::Finite(DEFAULT_MAX_BLOCKING_TIME),
    };

/// Enumeration representing the different types of destination order QoS policies.
#[derive(Debug, PartialEq, Eq, Clone, Copy, TypeSupport)]
pub enum DestinationOrderQosPolicyKind {
    /// Ordered by reception timestamp.
    ByReceptionTimestamp,
    /// Ordered by source timestamp.
    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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct DestinationOrderQosPolicy {
    /// Kind of destination order QoS associated with this policy.
    pub kind: DestinationOrderQosPolicyKind,
}

impl DestinationOrderQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            kind: DestinationOrderQosPolicyKind::ByReceptionTimestamp,
        }
    }
}

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

impl Default for DestinationOrderQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// Enumeration representing the different types of history QoS policies.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum HistoryQosPolicyKind {
    /// Keep number of samples indicated by the associated value.
    KeepLast(u32),
    /// Keep all samples.
    KeepAll,
}

impl TypeSupport for HistoryQosPolicyKind {
    #[inline]
    fn get_type_name() -> &'static str {
        "HistoryQosPolicyKind"
    }

    fn get_type() -> crate::xtypes::dynamic_type::DynamicType {
        extern crate alloc;
        let builder = dust_dds::xtypes::dynamic_type::DynamicTypeBuilderFactory::create_type(
            dust_dds::xtypes::dynamic_type::TypeDescriptor {
                kind: dust_dds::xtypes::dynamic_type::TypeKind::ENUM,
                name: alloc::string::String::from(Self::get_type_name()),
                base_type: None,
                discriminator_type: Some(
                    dust_dds::xtypes::dynamic_type::DynamicTypeBuilderFactory::get_primitive_type(
                        dust_dds::xtypes::dynamic_type::TypeKind::UINT8,
                    ),
                ),
                bound: alloc::vec::Vec::new(),
                element_type: None,
                key_element_type: None,
                extensibility_kind: dust_dds::xtypes::dynamic_type::ExtensibilityKind::Final,
                is_nested: false,
            },
        );
        builder.build()
    }

    fn create_sample(src: crate::xtypes::dynamic_type::DynamicData) -> Self {
        let discriminant = src.get_uint8_value(0).unwrap();
        match discriminant {
            0 => Self::KeepLast(1),
            1 => Self::KeepAll,
            d => panic!("Discriminant not valid {d:?}"),
        }
    }

    fn create_dynamic_sample(self) -> crate::xtypes::dynamic_type::DynamicData {
        let value = match self {
            HistoryQosPolicyKind::KeepLast(_) => 0,
            HistoryQosPolicyKind::KeepAll => 1,
        };
        let mut data = DynamicDataFactory::create_data(Self::get_type());
        data.set_uint8_value(0, value).unwrap();
        data
    }
}

/// 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)]
pub struct HistoryQosPolicy {
    /// Kind of history QoS associated with this policy.
    pub kind: HistoryQosPolicyKind,
}

impl HistoryQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            kind: HistoryQosPolicyKind::KeepLast(1),
        }
    }
}

impl dust_dds::infrastructure::type_support::TypeSupport for HistoryQosPolicy {
    #[inline]
    fn get_type_name() -> &'static str {
        "HistoryQosPolicy"
    }

    fn get_type() -> dust_dds::xtypes::dynamic_type::DynamicType {
        extern crate alloc;
        let mut builder = dust_dds::xtypes::dynamic_type::DynamicTypeBuilderFactory::create_type(
            dust_dds::xtypes::dynamic_type::TypeDescriptor {
                kind: dust_dds::xtypes::dynamic_type::TypeKind::STRUCTURE,
                name: alloc::string::String::from(Self::get_type_name()),
                base_type: None,
                discriminator_type: None,
                bound: alloc::vec::Vec::new(),
                element_type: None,
                key_element_type: None,
                extensibility_kind: dust_dds::xtypes::dynamic_type::ExtensibilityKind::Appendable,
                is_nested: true,
            },
        );
        builder
            .add_member(dust_dds::xtypes::dynamic_type::MemberDescriptor {
                name: alloc::string::String::from("kind"),
                id: 0,
                r#type: HistoryQosPolicyKind::get_type(),
                default_value: None,
                index: 0u32,
                try_construct_kind: dust_dds::xtypes::dynamic_type::TryConstructKind::UseDefault,
                label: alloc::vec::Vec::new(),
                is_key: false,
                is_optional: false,
                is_must_understand: true,
                is_shared: false,
                is_default_label: false,
            })
            .unwrap();
        builder
            .add_member(dust_dds::xtypes::dynamic_type::MemberDescriptor {
                name: alloc::string::String::from("depth"),
                id: 1,
                r#type:
                    dust_dds::xtypes::dynamic_type::DynamicTypeBuilderFactory::get_primitive_type(
                        TypeKind::INT32,
                    ),
                default_value: None,
                index: 1u32,
                try_construct_kind: dust_dds::xtypes::dynamic_type::TryConstructKind::UseDefault,
                label: alloc::vec::Vec::new(),
                is_key: false,
                is_optional: false,
                is_must_understand: true,
                is_shared: false,
                is_default_label: false,
            })
            .unwrap();
        builder.build()
    }

    fn create_sample(src: crate::xtypes::dynamic_type::DynamicData) -> Self {
        let kind = src.get_complex_value(0).cloned().unwrap();
        let depth = src.get_int32_value(1).unwrap();
        let qos_policy_kind = HistoryQosPolicyKind::create_sample(kind);
        match qos_policy_kind {
            HistoryQosPolicyKind::KeepLast(_) => HistoryQosPolicy {
                kind: HistoryQosPolicyKind::KeepLast(*depth as u32),
            },
            HistoryQosPolicyKind::KeepAll => HistoryQosPolicy {
                kind: HistoryQosPolicyKind::KeepAll,
            },
        }
    }

    fn create_dynamic_sample(self) -> crate::xtypes::dynamic_type::DynamicData {
        let mut data = DynamicDataFactory::create_data(Self::get_type());
        match self.kind {
            HistoryQosPolicyKind::KeepLast(depth) => {
                data.set_complex_value(0, self.kind.create_dynamic_sample())
                    .unwrap();
                data.set_int32_value(1, depth as i32).unwrap();
            }
            HistoryQosPolicyKind::KeepAll => {
                data.set_complex_value(0, self.kind.create_dynamic_sample())
                    .unwrap();
                data.set_int32_value(1, 0).unwrap();
            }
        }
        data
    }
}

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

impl Default for HistoryQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct ResourceLimitsQosPolicy {
    /// Maximum number of samples limit.
    pub max_samples: Length,
    /// Maximum number of instances limit.
    pub max_instances: Length,
    /// Maximum number of samples per instance limit.
    pub max_samples_per_instance: Length,
}

impl ResourceLimitsQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            max_samples: Length::Unlimited,
            max_instances: Length::Unlimited,
            max_samples_per_instance: Length::Unlimited,
        }
    }
}

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

impl Default for ResourceLimitsQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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 {
    /// Value of auto-enable created entities.
    pub autoenable_created_entities: bool,
}

impl EntityFactoryQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            autoenable_created_entities: true,
        }
    }
}

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

impl Default for EntityFactoryQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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 {
    /// Value of auto-dispose unregistered instances.
    pub autodispose_unregistered_instances: bool,
}

impl WriterDataLifecycleQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            autodispose_unregistered_instances: true,
        }
    }
}

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

impl Default for WriterDataLifecycleQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

/// 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 {
    /// Time duration to auto purge samples with no writer.
    pub autopurge_nowriter_samples_delay: DurationKind,
    /// Time duration to auto purge disposed samples.
    pub autopurge_disposed_samples_delay: DurationKind,
}

impl ReaderDataLifecycleQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            autopurge_nowriter_samples_delay: DurationKind::Infinite,
            autopurge_disposed_samples_delay: DurationKind::Infinite,
        }
    }
}

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

impl Default for ReaderDataLifecycleQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

impl From<&ReliabilityQosPolicy> for ReliabilityKind {
    fn from(value: &ReliabilityQosPolicy) -> Self {
        match value.kind {
            ReliabilityQosPolicyKind::BestEffort => ReliabilityKind::BestEffort,
            ReliabilityQosPolicyKind::Reliable => ReliabilityKind::Reliable,
        }
    }
}

impl From<&DurabilityQosPolicy> for DurabilityKind {
    fn from(value: &DurabilityQosPolicy) -> Self {
        match value.kind {
            DurabilityQosPolicyKind::Volatile => DurabilityKind::Volatile,
            DurabilityQosPolicyKind::TransientLocal => DurabilityKind::TransientLocal,
            DurabilityQosPolicyKind::Transient => DurabilityKind::Transient,
            DurabilityQosPolicyKind::Persistent => DurabilityKind::Persistent,
        }
    }
}

/*******  DDS X-TYPES Extension **********/

type DataRepresentationId = u16;
/// XCDR data representation
pub const XCDR_DATA_REPRESENTATION: DataRepresentationId = 0;
/// XML data representation
pub const XML_DATA_REPRESENTATION: DataRepresentationId = 1;
/// XCDR2 data representation
pub const XCDR2_DATA_REPRESENTATION: DataRepresentationId = 2;
/// Built-in topic data representation
pub(crate) const BUILT_IN_DATA_REPRESENTATION: DataRepresentationId = 9999;
type DataRepresentationIdSeq = Vec<DataRepresentationId>;

/// This policy is a DDS-XTypes extension and represents the standard data Representations available.
/// [`DataWriter`](crate::publication::data_writer::DataWriter) and [`DataReader`](crate::subscription::data_reader::DataReader) must be able to negotiate which data representation(s) to use.
#[derive(Debug, PartialEq, Eq, Clone, TypeSupport)]
#[dust_dds(extensibility = "appendable", nested)]
pub struct DataRepresentationQosPolicy {
    /// List of data representation values
    pub value: DataRepresentationIdSeq,
}

impl DataRepresentationQosPolicy {
    pub const fn const_default() -> Self {
        Self {
            value: DataRepresentationIdSeq::new(),
        }
    }
}

impl QosPolicy for DataRepresentationQosPolicy {
    fn name(&self) -> &str {
        DATA_REPRESENTATION_QOS_POLICY_NAME
    }
}

impl Default for DataRepresentationQosPolicy {
    fn default() -> Self {
        Self::const_default()
    }
}

#[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));
    }
}