1use core::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct ProtocolVersion {
11 pub major: u8,
13 pub minor: u8,
15}
16
17impl ProtocolVersion {
18 pub const RTPS_2_5: Self = Self { major: 2, minor: 5 };
20
21 pub const fn new(major: u8, minor: u8) -> Self {
23 Self { major, minor }
24 }
25}
26
27impl Default for ProtocolVersion {
28 fn default() -> Self {
29 Self::RTPS_2_5
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub struct VendorId(pub [u8; 2]);
36
37impl VendorId {
38 pub const HDDS: Self = Self([0x01, 0x14]); pub const fn new(id: [u8; 2]) -> Self {
43 Self(id)
44 }
45}
46
47impl Default for VendorId {
48 fn default() -> Self {
49 Self::HDDS
50 }
51}
52
53#[derive(Clone, Copy, PartialEq, Eq, Hash)]
57pub struct GuidPrefix(pub [u8; 12]);
58
59impl GuidPrefix {
60 pub const UNKNOWN: Self = Self([0; 12]);
62
63 pub const fn new(bytes: [u8; 12]) -> Self {
65 Self(bytes)
66 }
67
68 pub const fn as_bytes(&self) -> &[u8; 12] {
70 &self.0
71 }
72}
73
74impl Default for GuidPrefix {
75 fn default() -> Self {
76 Self::UNKNOWN
77 }
78}
79
80impl fmt::Debug for GuidPrefix {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(f, "GuidPrefix(")?;
83 for (i, b) in self.0.iter().enumerate() {
84 if i > 0 {
85 write!(f, ":")?;
86 }
87 write!(f, "{:02x}", b)?;
88 }
89 write!(f, ")")
90 }
91}
92
93#[derive(Clone, Copy, PartialEq, Eq, Hash)]
97pub struct EntityId(pub [u8; 4]);
98
99impl EntityId {
100 pub const UNKNOWN: Self = Self([0x00, 0x00, 0x00, 0x00]);
102
103 pub const PARTICIPANT: Self = Self([0x00, 0x00, 0x01, 0xc1]);
105
106 pub const SEDP_BUILTIN_PUBLICATIONS_WRITER: Self = Self([0x00, 0x00, 0x03, 0xc2]);
108
109 pub const SEDP_BUILTIN_PUBLICATIONS_READER: Self = Self([0x00, 0x00, 0x03, 0xc7]);
111
112 pub const SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: Self = Self([0x00, 0x00, 0x04, 0xc2]);
114
115 pub const SEDP_BUILTIN_SUBSCRIPTIONS_READER: Self = Self([0x00, 0x00, 0x04, 0xc7]);
117
118 pub const fn new(bytes: [u8; 4]) -> Self {
120 Self(bytes)
121 }
122
123 pub const fn as_bytes(&self) -> &[u8; 4] {
125 &self.0
126 }
127
128 pub const fn is_builtin(&self) -> bool {
130 self.0[3] & 0xc0 == 0xc0
132 }
133
134 pub const fn is_writer(&self) -> bool {
136 self.0[3] & 0x02 == 0x02
138 }
139
140 pub const fn is_reader(&self) -> bool {
142 self.0[3] & 0x07 == 0x07
144 }
145}
146
147impl Default for EntityId {
148 fn default() -> Self {
149 Self::UNKNOWN
150 }
151}
152
153impl fmt::Debug for EntityId {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 write!(
156 f,
157 "EntityId({:02x}{:02x}{:02x}{:02x})",
158 self.0[0], self.0[1], self.0[2], self.0[3]
159 )
160 }
161}
162
163#[derive(Clone, Copy, PartialEq, Eq, Hash)]
165pub struct GUID {
166 pub prefix: GuidPrefix,
168 pub entity_id: EntityId,
170}
171
172impl GUID {
173 pub const UNKNOWN: Self = Self {
175 prefix: GuidPrefix::UNKNOWN,
176 entity_id: EntityId::UNKNOWN,
177 };
178
179 pub const fn new(prefix: GuidPrefix, entity_id: EntityId) -> Self {
181 Self { prefix, entity_id }
182 }
183
184 pub fn to_bytes(&self) -> [u8; 16] {
186 let mut bytes = [0u8; 16];
187 bytes[0..12].copy_from_slice(&self.prefix.0);
188 bytes[12..16].copy_from_slice(&self.entity_id.0);
189 bytes
190 }
191
192 pub fn from_bytes(bytes: [u8; 16]) -> Self {
194 let mut prefix = [0u8; 12];
195 let mut entity_id = [0u8; 4];
196 prefix.copy_from_slice(&bytes[0..12]);
197 entity_id.copy_from_slice(&bytes[12..16]);
198 Self {
199 prefix: GuidPrefix(prefix),
200 entity_id: EntityId(entity_id),
201 }
202 }
203}
204
205impl Default for GUID {
206 fn default() -> Self {
207 Self::UNKNOWN
208 }
209}
210
211impl fmt::Debug for GUID {
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 write!(f, "GUID({:?}:{:?})", self.prefix, self.entity_id)
214 }
215}
216
217#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
221pub struct SequenceNumber(pub i64);
222
223impl SequenceNumber {
224 pub const UNKNOWN: Self = Self(-1);
226
227 pub const MIN: Self = Self(1);
229
230 pub const fn new(value: i64) -> Self {
232 Self(value)
233 }
234
235 pub const fn value(&self) -> i64 {
237 self.0
238 }
239
240 pub fn increment(&mut self) {
242 self.0 = self.0.saturating_add(1);
243 }
244
245 pub const fn next(self) -> Self {
247 Self(self.0 + 1)
248 }
249}
250
251impl Default for SequenceNumber {
252 fn default() -> Self {
253 Self::MIN
254 }
255}
256
257impl fmt::Debug for SequenceNumber {
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 write!(f, "SequenceNumber({})", self.0)
260 }
261}
262
263impl fmt::Display for SequenceNumber {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 write!(f, "{}", self.0)
266 }
267}
268
269#[derive(Clone, Copy, PartialEq, Eq)]
273pub struct Locator {
274 pub kind: i32,
276 pub port: u32,
278 pub address: [u8; 16],
280}
281
282impl Locator {
283 pub const INVALID: Self = Self {
285 kind: -1,
286 port: 0,
287 address: [0; 16],
288 };
289
290 pub const KIND_UDPV4: i32 = 1;
292
293 pub const KIND_UDPV6: i32 = 2;
295
296 pub const fn udpv4(ip: [u8; 4], port: u16) -> Self {
298 let mut address = [0u8; 16];
299 address[10] = 0xff;
301 address[11] = 0xff;
302 address[12] = ip[0];
303 address[13] = ip[1];
304 address[14] = ip[2];
305 address[15] = ip[3];
306
307 Self {
308 kind: Self::KIND_UDPV4,
309 port: port as u32,
310 address,
311 }
312 }
313
314 pub const fn is_valid(&self) -> bool {
316 self.kind > 0 && self.port > 0
317 }
318}
319
320impl Default for Locator {
321 fn default() -> Self {
322 Self::INVALID
323 }
324}
325
326impl fmt::Debug for Locator {
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 if self.kind == Self::KIND_UDPV4 {
329 write!(
330 f,
331 "Locator(UDPv4, {}.{}.{}.{}:{})",
332 self.address[12], self.address[13], self.address[14], self.address[15], self.port
333 )
334 } else if self.kind == Self::KIND_UDPV6 {
335 write!(f, "Locator(UDPv6, [...]:{})", self.port)
336 } else {
337 write!(f, "Locator(Invalid)")
338 }
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345
346 #[test]
347 fn test_protocol_version() {
348 let v = ProtocolVersion::RTPS_2_5;
349 assert_eq!(v.major, 2);
350 assert_eq!(v.minor, 5);
351 }
352
353 #[test]
354 fn test_guid_prefix() {
355 let prefix = GuidPrefix::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
356 assert_eq!(prefix.as_bytes()[0], 1);
357 assert_eq!(prefix.as_bytes()[11], 12);
358 }
359
360 #[test]
361 fn test_entity_id_builtin() {
362 assert!(EntityId::PARTICIPANT.is_builtin());
363 assert!(EntityId::SEDP_BUILTIN_PUBLICATIONS_WRITER.is_builtin());
364 assert!(!EntityId::UNKNOWN.is_builtin());
365 }
366
367 #[test]
368 fn test_entity_id_writer_reader() {
369 assert!(EntityId::SEDP_BUILTIN_PUBLICATIONS_WRITER.is_writer());
370 assert!(EntityId::SEDP_BUILTIN_PUBLICATIONS_READER.is_reader());
371 }
372
373 #[test]
374 fn test_guid_conversion() {
375 let guid = GUID::new(
376 GuidPrefix::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
377 EntityId::new([13, 14, 15, 16]),
378 );
379
380 let bytes = guid.to_bytes();
381 assert_eq!(bytes[0], 1);
382 assert_eq!(bytes[11], 12);
383 assert_eq!(bytes[12], 13);
384 assert_eq!(bytes[15], 16);
385
386 let restored = GUID::from_bytes(bytes);
387 assert_eq!(restored, guid);
388 }
389
390 #[test]
391 fn test_sequence_number() {
392 let mut seq = SequenceNumber::new(1);
393 assert_eq!(seq.value(), 1);
394
395 seq.increment();
396 assert_eq!(seq.value(), 2);
397
398 let next = seq.next();
399 assert_eq!(next.value(), 3);
400 assert_eq!(seq.value(), 2); }
402
403 #[test]
404 fn test_locator_udpv4() {
405 let loc = Locator::udpv4([192, 168, 1, 100], 7400);
406 assert_eq!(loc.kind, Locator::KIND_UDPV4);
407 assert_eq!(loc.port, 7400);
408 assert_eq!(loc.address[12], 192);
409 assert_eq!(loc.address[13], 168);
410 assert_eq!(loc.address[14], 1);
411 assert_eq!(loc.address[15], 100);
412 assert!(loc.is_valid());
413 }
414
415 #[test]
416 fn test_locator_invalid() {
417 let loc = Locator::INVALID;
418 assert!(!loc.is_valid());
419 }
420}