rustdds/messages/submessages/
submessage.rs

1use speedy::{Context, Writable, Writer};
2use enumflags2::BitFlags;
3
4use crate::{
5  messages::submessages::{
6    ack_nack::AckNack, data::Data, data_frag::DataFrag, gap::Gap, heartbeat::Heartbeat,
7    heartbeat_frag::HeartbeatFrag, info_destination::InfoDestination, info_reply::InfoReply,
8    info_source::InfoSource, info_timestamp::InfoTimestamp, nack_frag::NackFrag,
9    submessage_flag::*,
10  },
11  structure::guid::EntityId,
12};
13#[cfg(feature = "security")]
14use super::{
15  secure_body::SecureBody, secure_postfix::SecurePostfix, secure_prefix::SecurePrefix,
16  secure_rtps_postfix::SecureRTPSPostfix, secure_rtps_prefix::SecureRTPSPrefix,
17};
18
19// TODO: These messages are structured a bit oddly. Why is flags separate from
20// the submessage proper?
21
22#[derive(Debug, PartialEq, Eq, Clone)]
23pub enum WriterSubmessage {
24  Data(Data, BitFlags<DATA_Flags>),
25  DataFrag(DataFrag, BitFlags<DATAFRAG_Flags>),
26  Gap(Gap, BitFlags<GAP_Flags>),
27  Heartbeat(Heartbeat, BitFlags<HEARTBEAT_Flags>),
28  #[allow(dead_code)] // Functionality not yet implemented
29  HeartbeatFrag(HeartbeatFrag, BitFlags<HEARTBEATFRAG_Flags>),
30}
31
32// we must write this manually, because
33// 1) we cannot implement Writable for *Flags defined using enumflags2, as they
34// are foreign types (coherence rules) 2) Writer should not use any enum variant
35// tag in this type, as we have SubmessageHeader already.
36impl<C: Context> Writable<C> for WriterSubmessage {
37  fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
38    match self {
39      WriterSubmessage::Data(s, _f) => writer.write_value(s),
40      WriterSubmessage::DataFrag(s, _f) => writer.write_value(s),
41      WriterSubmessage::Gap(s, _f) => writer.write_value(s),
42      WriterSubmessage::Heartbeat(s, _f) => writer.write_value(s),
43      WriterSubmessage::HeartbeatFrag(s, _f) => writer.write_value(s),
44    }
45  }
46}
47
48#[derive(Debug, PartialEq, Eq, Clone)]
49pub enum ReaderSubmessage {
50  AckNack(AckNack, BitFlags<ACKNACK_Flags>),
51  NackFrag(NackFrag, BitFlags<NACKFRAG_Flags>),
52}
53
54// we must write this manually, because
55// 1) we cannot implement Writable for *Flags defined using enumflags2, as they
56// are foreign types (coherence rules) 2) Writer should not use any enum variant
57// tag in this type, as we have SubmessageHeader already.
58impl<C: Context> Writable<C> for ReaderSubmessage {
59  fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
60    match self {
61      ReaderSubmessage::AckNack(s, _f) => writer.write_value(s),
62      ReaderSubmessage::NackFrag(s, _f) => writer.write_value(s),
63    }
64  }
65}
66
67/// New submessage types: section 7.3.6 of the Security specification (v. 1.1)
68#[cfg(feature = "security")]
69#[derive(Debug, PartialEq, Eq, Clone)]
70#[allow(clippy::enum_variant_names)] // We are using variant names from the spec
71pub enum SecuritySubmessage {
72  SecureBody(SecureBody, BitFlags<SECUREBODY_Flags>),
73  SecurePrefix(SecurePrefix, BitFlags<SECUREPREFIX_Flags>),
74  SecurePostfix(SecurePostfix, BitFlags<SECUREPOSTFIX_Flags>),
75  SecureRTPSPrefix(SecureRTPSPrefix, BitFlags<SECURERTPSPREFIX_Flags>),
76  SecureRTPSPostfix(SecureRTPSPostfix, BitFlags<SECURERTPSPOSTFIX_Flags>),
77}
78
79// we must write this manually, because
80// 1) we cannot implement Writable for *Flags defined using enumflags2, as they
81// are foreign types (coherence rules) 2) Writer should not use any enum variant
82// tag in this type, as we have SubmessageHeader already.
83#[cfg(feature = "security")]
84impl<C: Context> Writable<C> for SecuritySubmessage {
85  fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
86    match self {
87      SecuritySubmessage::SecureBody(s, _f) => writer.write_value(s),
88      SecuritySubmessage::SecurePrefix(s, _f) => writer.write_value(s),
89      SecuritySubmessage::SecurePostfix(s, _f) => writer.write_value(s),
90      SecuritySubmessage::SecureRTPSPrefix(s, _f) => writer.write_value(s),
91      SecuritySubmessage::SecureRTPSPostfix(s, _f) => writer.write_value(s),
92    }
93  }
94}
95
96#[derive(Debug, PartialEq, Eq, Clone)]
97#[allow(clippy::enum_variant_names)]
98pub enum InterpreterSubmessage {
99  InfoSource(InfoSource, BitFlags<INFOSOURCE_Flags>),
100  InfoDestination(InfoDestination, BitFlags<INFODESTINATION_Flags>),
101  InfoReply(InfoReply, BitFlags<INFOREPLY_Flags>),
102  InfoTimestamp(InfoTimestamp, BitFlags<INFOTIMESTAMP_Flags>),
103  // Pad(Pad), // Pad message does not need to be processed above serialization layer
104}
105
106// See notes on impl Writer for EntitySubmessage
107impl<C: Context> Writable<C> for InterpreterSubmessage {
108  fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
109    match self {
110      InterpreterSubmessage::InfoSource(s, _f) => writer.write_value(s),
111      InterpreterSubmessage::InfoDestination(s, _f) => writer.write_value(s),
112      InterpreterSubmessage::InfoReply(s, _f) => writer.write_value(s),
113      InterpreterSubmessage::InfoTimestamp(s, _f) => match s {
114        InfoTimestamp { timestamp: None } => Ok(()), // serialization is empty string
115        InfoTimestamp {
116          timestamp: Some(ts),
117        } => writer.write_value(ts),
118      },
119    }
120  }
121}
122
123#[derive(Debug)]
124pub enum AckSubmessage {
125  AckNack(AckNack),
126  #[allow(dead_code)] // Functionality not yet implemented
127  NackFrag(NackFrag),
128}
129
130impl AckSubmessage {
131  pub fn writer_id(&self) -> EntityId {
132    match self {
133      AckSubmessage::AckNack(a) => a.writer_id,
134      AckSubmessage::NackFrag(a) => a.writer_id,
135    }
136  }
137}
138
139pub trait HasEntityIds {
140  fn receiver_entity_id(&self) -> EntityId;
141  fn sender_entity_id(&self) -> EntityId;
142}
143
144impl HasEntityIds for WriterSubmessage {
145  fn receiver_entity_id(&self) -> EntityId {
146    match self {
147      WriterSubmessage::Data(s, _f) => s.receiver_entity_id(),
148      WriterSubmessage::DataFrag(s, _f) => s.receiver_entity_id(),
149      WriterSubmessage::Gap(s, _f) => s.receiver_entity_id(),
150      WriterSubmessage::Heartbeat(s, _f) => s.receiver_entity_id(),
151      WriterSubmessage::HeartbeatFrag(s, _f) => s.receiver_entity_id(),
152    }
153  }
154  fn sender_entity_id(&self) -> EntityId {
155    match self {
156      WriterSubmessage::Data(s, _f) => s.sender_entity_id(),
157      WriterSubmessage::DataFrag(s, _f) => s.sender_entity_id(),
158      WriterSubmessage::Gap(s, _f) => s.sender_entity_id(),
159      WriterSubmessage::Heartbeat(s, _f) => s.sender_entity_id(),
160      WriterSubmessage::HeartbeatFrag(s, _f) => s.sender_entity_id(),
161    }
162  }
163}
164
165impl HasEntityIds for ReaderSubmessage {
166  fn receiver_entity_id(&self) -> EntityId {
167    match self {
168      ReaderSubmessage::AckNack(s, _f) => s.receiver_entity_id(),
169      ReaderSubmessage::NackFrag(s, _f) => s.receiver_entity_id(),
170    }
171  }
172  fn sender_entity_id(&self) -> EntityId {
173    match self {
174      ReaderSubmessage::AckNack(s, _f) => s.sender_entity_id(),
175      ReaderSubmessage::NackFrag(s, _f) => s.sender_entity_id(),
176    }
177  }
178}