rtps_parser/rtps/
types.rs

1use super::messages::overall_structure::{WriteBytes, WriteEndianness};
2use byteorder::ByteOrder;
3use dust_dds::serialized_payload::cdr::{serialize::CdrSerialize, deserialize::CdrDeserialize};
4use std::ops::{Add, AddAssign, Sub, SubAssign};
5
6///
7/// This files shall only contain the types as listed in the DDSI-RTPS Version 2.5
8/// Table 8.2 - Types of the attributes that appear in the RTPS Entities and Classes
9///
10
11type Octet = u8;
12type Long = i32;
13type UnsignedLong = u32;
14
15impl WriteBytes for Long {
16    #[inline]
17    fn write_bytes(&self, buf: &mut [u8]) -> usize {
18        WriteEndianness::write_i32(buf, *self);
19        4
20    }
21}
22
23impl WriteBytes for UnsignedLong {
24    #[inline]
25    fn write_bytes(&self, buf: &mut [u8]) -> usize {
26        WriteEndianness::write_u32(buf, *self);
27        4
28    }
29}
30
31impl WriteBytes for u16 {
32    #[inline]
33    fn write_bytes(&self, buf: &mut [u8]) -> usize {
34        WriteEndianness::write_u16(buf, *self);
35        2
36    }
37}
38
39impl WriteBytes for i16 {
40    #[inline]
41    fn write_bytes(&self, buf: &mut [u8]) -> usize {
42        WriteEndianness::write_i16(buf, *self);
43        2
44    }
45}
46
47impl<const N: usize> WriteBytes for [Octet; N] {
48    #[inline]
49    fn write_bytes(&self, buf: &mut [u8]) -> usize {
50        buf[..self.len()].copy_from_slice(self);
51        N
52    }
53}
54
55/// GUID_t
56/// Type used to hold globally-unique RTPS-entity identifiers. These are identifiers used to uniquely refer to each RTPS Entity in the system.
57/// Must be possible to represent using 16 octets.
58/// The following values are reserved by the protocol: GUID_UNKNOWN
59#[derive(Clone, Copy, PartialEq, Eq, Debug, CdrSerialize, CdrDeserialize)]
60pub struct Guid {
61    prefix: GuidPrefix,
62    entity_id: EntityId,
63}
64
65impl Guid {
66    pub const fn new(prefix: GuidPrefix, entity_id: EntityId) -> Self {
67        Self { prefix, entity_id }
68    }
69
70    pub const fn prefix(&self) -> GuidPrefix {
71        self.prefix
72    }
73
74    pub const fn entity_id(&self) -> EntityId {
75        self.entity_id
76    }
77}
78
79pub const GUID_UNKNOWN: Guid = Guid::new(GUIDPREFIX_UNKNOWN, ENTITYID_UNKNOWN);
80
81impl From<[u8; 16]> for Guid {
82    fn from(value: [u8; 16]) -> Self {
83        let prefix = [
84            value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7],
85            value[8], value[9], value[10], value[11],
86        ];
87        let entity_id = EntityId::new([value[12], value[13], value[14]], value[15]);
88        Self { prefix, entity_id }
89    }
90}
91
92impl From<Guid> for [u8; 16] {
93    fn from(guid: Guid) -> Self {
94        [
95            guid.prefix[0],
96            guid.prefix[1],
97            guid.prefix[2],
98            guid.prefix[3],
99            guid.prefix[4],
100            guid.prefix[5],
101            guid.prefix[6],
102            guid.prefix[7],
103            guid.prefix[8],
104            guid.prefix[9],
105            guid.prefix[10],
106            guid.prefix[11],
107            guid.entity_id.entity_key[0],
108            guid.entity_id.entity_key[1],
109            guid.entity_id.entity_key[2],
110            guid.entity_id.entity_kind,
111        ]
112    }
113}
114
115/// GuidPrefix_t
116/// Type used to hold the prefix of the globally-unique RTPS-entity identifiers. The GUIDs of entities belonging to the same participant all have the same prefix (see 8.2.4.3).
117/// Must be possible to represent using 12 octets.
118/// The following values are reserved by the protocol: GUIDPREFIX_UNKNOWN
119pub type GuidPrefix = [u8; 12];
120pub const GUIDPREFIX_UNKNOWN: GuidPrefix = [0; 12];
121
122/// EntityId_t
123/// Type used to hold the suffix part of the globally-unique RTPS-entity identifiers. The
124/// EntityId_t uniquely identifies an Entity within a Participant. Must be possible to represent using 4 octets.
125/// The following values are reserved by the protocol: ENTITYID_UNKNOWN Additional pre-defined values are defined by the Discovery module in 8.5
126type OctetArray3 = [Octet; 3];
127#[derive(Clone, Copy, PartialEq, Eq, Debug, CdrSerialize, CdrDeserialize)]
128pub struct EntityId {
129    entity_key: OctetArray3,
130    entity_kind: Octet,
131}
132
133impl EntityId {
134    pub const fn new(entity_key: OctetArray3, entity_kind: Octet) -> Self {
135        Self {
136            entity_key,
137            entity_kind,
138        }
139    }
140
141    pub const fn entity_key(&self) -> OctetArray3 {
142        self.entity_key
143    }
144
145    pub const fn entity_kind(&self) -> Octet {
146        self.entity_kind
147    }
148}
149
150impl Default for EntityId {
151    fn default() -> Self {
152        ENTITYID_UNKNOWN
153    }
154}
155
156pub const ENTITYID_UNKNOWN: EntityId = EntityId::new([0; 3], USER_DEFINED_UNKNOWN);
157pub const ENTITYID_PARTICIPANT: EntityId = EntityId::new([0, 0, 0x01], BUILT_IN_PARTICIPANT);
158
159impl WriteBytes for EntityId {
160    #[inline]
161    fn write_bytes(&self, buf: &mut [u8]) -> usize {
162        self.entity_key().write_bytes(&mut buf[0..]);
163        self.entity_kind().write_bytes(&mut buf[3..]);
164        4
165    }
166}
167
168impl WriteBytes for Octet {
169    #[inline]
170    fn write_bytes(&self, buf: &mut [u8]) -> usize {
171        buf[0] = *self;
172        1
173    }
174}
175
176// Table 9.1 - entityKind octet of an EntityId_t
177pub const USER_DEFINED_UNKNOWN: Octet = 0x00;
178#[allow(dead_code)]
179pub const BUILT_IN_UNKNOWN: Octet = 0xc0;
180pub const BUILT_IN_PARTICIPANT: Octet = 0xc1;
181pub const USER_DEFINED_WRITER_WITH_KEY: Octet = 0x02;
182pub const BUILT_IN_WRITER_WITH_KEY: Octet = 0xc2;
183pub const USER_DEFINED_WRITER_NO_KEY: Octet = 0x03;
184#[allow(dead_code)]
185pub const BUILT_IN_WRITER_NO_KEY: Octet = 0xc3;
186pub const USER_DEFINED_READER_WITH_KEY: Octet = 0x07;
187pub const BUILT_IN_READER_WITH_KEY: Octet = 0xc7;
188pub const USER_DEFINED_READER_NO_KEY: Octet = 0x04;
189#[allow(dead_code)]
190pub const BUILT_IN_READER_NO_KEY: Octet = 0xc4;
191pub const USER_DEFINED_WRITER_GROUP: Octet = 0x08;
192pub const BUILT_IN_WRITER_GROUP: Octet = 0xc8;
193pub const USER_DEFINED_READER_GROUP: Octet = 0x09;
194pub const BUILT_IN_READER_GROUP: Octet = 0xc9;
195// Added in comparison to the RTPS standard
196pub const BUILT_IN_TOPIC: Octet = 0xca;
197pub const USER_DEFINED_TOPIC: Octet = 0x0a;
198
199/// SequenceNumber_t
200/// Type used to hold sequence numbers.
201/// Must be possible to represent using 64 bits.
202/// The following values are reserved by the protocol: SEQUENCENUMBER_UNKNOWN
203#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
204pub struct SequenceNumber {
205    high: Long,
206    low: UnsignedLong,
207}
208
209#[allow(dead_code)]
210pub const SEQUENCENUMBER_UNKNOWN: SequenceNumber = SequenceNumber::new(-1, 0);
211
212impl SequenceNumber {
213    pub const fn new(high: Long, low: UnsignedLong) -> Self {
214        Self { high, low }
215    }
216}
217impl From<SequenceNumber> for i64 {
218    fn from(value: SequenceNumber) -> Self {
219        ((value.high as i64) << 32) + value.low as i64
220    }
221}
222impl From<i64> for SequenceNumber {
223    fn from(value: i64) -> Self {
224        Self {
225            high: (value >> 32) as Long,
226            low: value as UnsignedLong,
227        }
228    }
229}
230impl Add for SequenceNumber {
231    type Output = Self;
232    fn add(self, rhs: SequenceNumber) -> Self::Output {
233        Self::from(<i64>::from(self) + <i64>::from(rhs))
234    }
235}
236impl Sub for SequenceNumber {
237    type Output = Self;
238    fn sub(self, rhs: Self) -> Self::Output {
239        Self::from(<i64>::from(self) - <i64>::from(rhs))
240    }
241}
242impl AddAssign<i64> for SequenceNumber {
243    fn add_assign(&mut self, rhs: i64) {
244        *self = Self::from(<i64>::from(*self) + rhs);
245    }
246}
247impl Add<i64> for SequenceNumber {
248    type Output = Self;
249    fn add(self, rhs: i64) -> Self::Output {
250        Self::from(<i64>::from(self) + rhs)
251    }
252}
253impl SubAssign<i64> for SequenceNumber {
254    fn sub_assign(&mut self, rhs: i64) {
255        *self = Self::from(<i64>::from(*self) - rhs);
256    }
257}
258impl Sub<i64> for SequenceNumber {
259    type Output = Self;
260    fn sub(self, rhs: i64) -> Self::Output {
261        Self::from(<i64>::from(self) - rhs)
262    }
263}
264
265impl WriteBytes for SequenceNumber {
266    #[inline]
267    fn write_bytes(&self, buf: &mut [u8]) -> usize {
268        self.high.write_bytes(&mut buf[0..]) + self.low.write_bytes(&mut buf[4..])
269    }
270}
271
272/// Locator_t
273/// Type used to represent the addressing information needed to send a message to an RTPS Endpoint using one of the supported transports.
274/// Should be able to hold a discriminator identifying the kind of transport, an address, and a port number. It must be possible to represent the discriminator and port number using 4 octets each, the address using 16 octets.
275/// The following values are reserved by the protocol: LOCATOR_INVALID LOCATOR_KIND_INVALID LOCATOR_KIND_RESERVED LOCATOR_KIND_UDP_V4 LOCATOR_KIND_UDP_V6 LOCATOR_ADDRESS_INVALID LOCATOR_PORT_INVALID
276#[derive(Clone, Copy, PartialEq, Eq, Debug, CdrSerialize, CdrDeserialize)]
277pub struct Locator {
278    kind: Long,
279    port: UnsignedLong,
280    address: [Octet; 16],
281}
282
283impl WriteBytes for Locator {
284    #[inline]
285    fn write_bytes(&self, buf: &mut [u8]) -> usize {
286        self.kind.write_bytes(&mut buf[0..]);
287        self.port.write_bytes(&mut buf[4..]);
288        self.address.write_bytes(&mut buf[8..]);
289        24
290    }
291}
292
293#[allow(dead_code)]
294pub const LOCATOR_KIND_INVALID: Long = -1;
295#[allow(dead_code)]
296pub const LOCATOR_KIND_RESERVED: Long = 0;
297pub const LOCATOR_KIND_UDP_V4: Long = 1;
298pub const LOCATOR_KIND_UDP_V6: Long = 2;
299pub const LOCATOR_PORT_INVALID: UnsignedLong = 0;
300pub const LOCATOR_ADDRESS_INVALID: [Octet; 16] = [0; 16];
301
302#[allow(dead_code)]
303pub const LOCATOR_INVALID: Locator = Locator::new(
304    LOCATOR_KIND_INVALID,
305    LOCATOR_PORT_INVALID,
306    LOCATOR_ADDRESS_INVALID,
307);
308
309impl Locator {
310    pub const fn new(kind: Long, port: UnsignedLong, address: [Octet; 16]) -> Self {
311        Self {
312            kind,
313            port,
314            address,
315        }
316    }
317    pub const fn kind(&self) -> Long {
318        self.kind
319    }
320    pub const fn port(&self) -> UnsignedLong {
321        self.port
322    }
323    pub const fn address(&self) -> [Octet; 16] {
324        self.address
325    }
326}
327
328/// TopicKind_t
329/// Enumeration used to distinguish whether a Topic has defined some fields within to be used as the ‘key’ that identifies data-instances within the Topic. See the DDS specification for more details on keys.
330/// The following values are reserved by the protocol: NO_KEY, WITH_KEY
331#[derive(Clone, Copy, PartialEq, Eq, Debug)]
332pub enum TopicKind {
333    NoKey,
334    WithKey,
335}
336
337/// ChangeKind_t
338/// Enumeration used to distinguish the kind of change that was made to a data-object. Includes changes to the data or the instance state of the data-object.
339/// It can take the values:
340/// ALIVE, ALIVE_FILTERED, NOT_ALIVE_DISPOSED, NOT_ALIVE_UNREGISTERED
341#[derive(Clone, Copy, PartialEq, Eq, Debug)]
342#[allow(dead_code)]
343pub enum ChangeKind {
344    Alive,
345    AliveFiltered,
346    NotAliveDisposed,
347    NotAliveUnregistered,
348    NotAliveDisposedUnregistered,
349}
350
351/// ChangeCount_t
352/// Type used to hold a counter representing the number of HistoryCache changes that belong to a certain category.
353/// For example, the number of changes that have been filtered for an RTPS Reader endpoint.
354#[allow(dead_code)]
355pub struct ChangeCount {
356    high: Long,
357    low: UnsignedLong,
358}
359
360/// ReliabilityKind_t
361/// Enumeration used to indicate the level of the reliability used for communications.
362/// It can take the values: BEST_EFFORT, RELIABLE.
363#[derive(Clone, Copy, Debug, PartialEq, Eq)]
364pub enum ReliabilityKind {
365    BestEffort,
366    Reliable,
367}
368
369/// InstanceHandle_t
370/// Type used to represent the identity of a data-object whose changes in value are communicated by the RTPS protocol.
371// Defined elsewhere in DDS
372
373/// ProtocolVersion_t
374/// Type used to represent the version of the RTPS protocol. The version is composed of a major and a minor version number. See also 8.6.
375/// The following values are reserved by the protocol: PROTOCOLVERSION PROTOCOLVERSION_1_0 PROTOCOLVERSION_1_1 PROTOCOLVERSION_2_0 PROTOCOLVERSION_2_1 PROTOCOLVERSION_2_2
376/// PROTOCOLVERSION_2_4
377/// PROTOCOLVERSION is an alias for the most recent version, in this case PROTOCOLVERSION_2_4
378#[derive(Clone, Copy, PartialEq, Eq, Debug, CdrSerialize, CdrDeserialize)]
379pub struct ProtocolVersion {
380    major: Octet,
381    minor: Octet,
382}
383
384impl WriteBytes for ProtocolVersion {
385    #[inline]
386    fn write_bytes(&self, buf: &mut [u8]) -> usize {
387        buf[0] = self.major;
388        buf[1] = self.minor;
389        2
390    }
391}
392
393pub const PROTOCOLVERSION: ProtocolVersion = PROTOCOLVERSION_2_4;
394#[allow(dead_code)]
395pub const PROTOCOLVERSION_1_0: ProtocolVersion = ProtocolVersion::new(1, 0);
396#[allow(dead_code)]
397pub const PROTOCOLVERSION_1_1: ProtocolVersion = ProtocolVersion::new(1, 1);
398#[allow(dead_code)]
399pub const PROTOCOLVERSION_2_0: ProtocolVersion = ProtocolVersion::new(2, 0);
400#[allow(dead_code)]
401pub const PROTOCOLVERSION_2_1: ProtocolVersion = ProtocolVersion::new(2, 1);
402#[allow(dead_code)]
403pub const PROTOCOLVERSION_2_2: ProtocolVersion = ProtocolVersion::new(2, 2);
404#[allow(dead_code)]
405pub const PROTOCOLVERSION_2_3: ProtocolVersion = ProtocolVersion::new(2, 3);
406pub const PROTOCOLVERSION_2_4: ProtocolVersion = ProtocolVersion::new(2, 4);
407
408impl ProtocolVersion {
409    pub const fn new(major: Octet, minor: Octet) -> Self {
410        Self { major, minor }
411    }
412    pub const fn _major(&self) -> Octet {
413        self.major
414    }
415    pub const fn _minor(&self) -> Octet {
416        self.minor
417    }
418}
419
420/// VendorId_t
421/// Type used to represent the vendor of the service implementing the RTPS protocol. The possible values for the vendorId are assigned by the OMG.
422/// The following values are reserved by the protocol: VENDORID_UNKNOWN
423pub type VendorId = [Octet; 2];
424
425#[allow(dead_code)]
426pub const VENDOR_ID_UNKNOWN: VendorId = [0, 0];
427pub const VENDOR_ID_S2E: VendorId = [0x01, 0x14];
428
429#[cfg(test)]
430mod tests {
431    use super::*;
432    use crate::rtps::messages::overall_structure::into_bytes_vec;
433
434    #[test]
435    fn serialize_sequence_number() {
436        let data = SequenceNumber::from(7);
437        let result = into_bytes_vec(data);
438        assert_eq!(
439            result,
440            vec![
441                0, 0, 0, 0, // high (long)
442                7, 0, 0, 0, // low (unsigned long)
443            ]
444        );
445    }
446
447    #[test]
448    fn serialize_entity_id() {
449        let data = EntityId::new([1, 2, 3], 0x04);
450        assert_eq!(
451            into_bytes_vec(data),
452            vec![
453            1, 2, 3, 0x04, //value (long)
454        ]
455        );
456    }
457}