zerodds_discovery/
capabilities.rs1extern crate alloc;
16use zerodds_rtps::participant_data::endpoint_flag;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
22pub struct PeerCapabilities {
23 pub raw: u32,
26 pub has_spdp: bool,
28 pub has_sedp_publications: bool,
30 pub has_sedp_subscriptions: bool,
32 pub has_wlp: bool,
34 pub has_type_lookup: bool,
36 pub has_topics_discovery: bool,
38 pub has_secure_publications: bool,
40 pub has_secure_subscriptions: bool,
42 pub has_secure_wlp: bool,
44 pub has_stateless_auth: bool,
46 pub has_volatile_secure: bool,
48 pub has_secure_participant: bool,
50}
51
52impl PeerCapabilities {
53 #[must_use]
55 pub fn from_bits(raw: u32) -> Self {
56 let bit_pair_set = |a: u32, b: u32| -> bool { raw & a != 0 && raw & b != 0 };
57 Self {
58 raw,
59 has_spdp: bit_pair_set(
60 endpoint_flag::PARTICIPANT_ANNOUNCER,
61 endpoint_flag::PARTICIPANT_DETECTOR,
62 ),
63 has_sedp_publications: bit_pair_set(
64 endpoint_flag::PUBLICATIONS_ANNOUNCER,
65 endpoint_flag::PUBLICATIONS_DETECTOR,
66 ),
67 has_sedp_subscriptions: bit_pair_set(
68 endpoint_flag::SUBSCRIPTIONS_ANNOUNCER,
69 endpoint_flag::SUBSCRIPTIONS_DETECTOR,
70 ),
71 has_wlp: bit_pair_set(
72 endpoint_flag::PARTICIPANT_MESSAGE_DATA_WRITER,
73 endpoint_flag::PARTICIPANT_MESSAGE_DATA_READER,
74 ),
75 has_type_lookup: (raw & endpoint_flag::TYPE_LOOKUP_REQUEST != 0)
76 && (raw & endpoint_flag::TYPE_LOOKUP_REPLY != 0),
77 has_topics_discovery: bit_pair_set(
78 endpoint_flag::TOPICS_ANNOUNCER,
79 endpoint_flag::TOPICS_DETECTOR,
80 ),
81 has_secure_publications: bit_pair_set(
82 endpoint_flag::PUBLICATIONS_SECURE_WRITER,
83 endpoint_flag::PUBLICATIONS_SECURE_READER,
84 ),
85 has_secure_subscriptions: bit_pair_set(
86 endpoint_flag::SUBSCRIPTIONS_SECURE_WRITER,
87 endpoint_flag::SUBSCRIPTIONS_SECURE_READER,
88 ),
89 has_secure_wlp: bit_pair_set(
90 endpoint_flag::PARTICIPANT_MESSAGE_SECURE_WRITER,
91 endpoint_flag::PARTICIPANT_MESSAGE_SECURE_READER,
92 ),
93 has_stateless_auth: bit_pair_set(
94 endpoint_flag::PARTICIPANT_STATELESS_MESSAGE_WRITER,
95 endpoint_flag::PARTICIPANT_STATELESS_MESSAGE_READER,
96 ),
97 has_volatile_secure: bit_pair_set(
98 endpoint_flag::PARTICIPANT_VOLATILE_MESSAGE_SECURE_WRITER,
99 endpoint_flag::PARTICIPANT_VOLATILE_MESSAGE_SECURE_READER,
100 ),
101 has_secure_participant: bit_pair_set(
102 endpoint_flag::PARTICIPANT_SECURE_WRITER,
103 endpoint_flag::PARTICIPANT_SECURE_READER,
104 ),
105 }
106 }
107
108 #[must_use]
113 pub fn supports_security(&self) -> bool {
114 self.raw & endpoint_flag::ALL_SECURE != 0
115 }
116
117 #[must_use]
121 pub fn fully_standard(&self) -> bool {
122 self.raw & endpoint_flag::ALL_STANDARD == endpoint_flag::ALL_STANDARD
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn capabilities_from_zero_bitmask_is_all_false() {
132 let c = PeerCapabilities::from_bits(0);
133 assert_eq!(c.raw, 0);
134 assert!(!c.has_spdp);
135 assert!(!c.has_sedp_publications);
136 assert!(!c.has_sedp_subscriptions);
137 assert!(!c.has_wlp);
138 assert!(!c.has_topics_discovery);
139 assert!(!c.supports_security());
140 assert!(!c.fully_standard());
141 }
142
143 #[test]
144 fn capabilities_full_standard_bundle() {
145 let c = PeerCapabilities::from_bits(endpoint_flag::ALL_STANDARD);
146 assert!(c.has_spdp);
147 assert!(c.has_sedp_publications);
148 assert!(c.has_sedp_subscriptions);
149 assert!(c.has_wlp);
150 assert!(!c.has_topics_discovery);
154 assert!(c.fully_standard());
155 assert!(!c.supports_security());
157 assert!(!c.has_secure_publications);
158 }
159
160 #[test]
161 fn capabilities_topics_discovery_when_explicitly_added() {
162 let mask = endpoint_flag::ALL_STANDARD
166 | endpoint_flag::TOPICS_ANNOUNCER
167 | endpoint_flag::TOPICS_DETECTOR;
168 let c = PeerCapabilities::from_bits(mask);
169 assert!(c.has_topics_discovery);
170 }
171
172 #[test]
173 fn capabilities_full_secure_bundle() {
174 let c = PeerCapabilities::from_bits(endpoint_flag::ALL_SECURE);
175 assert!(c.supports_security());
176 assert!(c.has_secure_publications);
177 assert!(c.has_secure_subscriptions);
178 assert!(c.has_secure_wlp);
179 assert!(c.has_stateless_auth);
180 assert!(c.has_volatile_secure);
181 assert!(c.has_secure_participant);
182 assert!(!c.has_spdp);
184 assert!(!c.has_wlp);
185 }
186
187 #[test]
188 fn capabilities_partial_pair_does_not_count() {
189 let c = PeerCapabilities::from_bits(endpoint_flag::PUBLICATIONS_ANNOUNCER);
191 assert!(!c.has_sedp_publications);
192 }
193
194 #[test]
195 fn capabilities_combined_standard_and_secure() {
196 let mask = endpoint_flag::ALL_STANDARD | endpoint_flag::ALL_SECURE;
197 let c = PeerCapabilities::from_bits(mask);
198 assert!(c.fully_standard());
199 assert!(c.supports_security());
200 assert!(c.has_wlp);
201 assert!(c.has_secure_wlp);
202 }
203
204 #[test]
205 fn capabilities_legacy_peer_only_spdp_sedp() {
206 let mask = endpoint_flag::PARTICIPANT_ANNOUNCER
208 | endpoint_flag::PARTICIPANT_DETECTOR
209 | endpoint_flag::PUBLICATIONS_ANNOUNCER
210 | endpoint_flag::PUBLICATIONS_DETECTOR
211 | endpoint_flag::SUBSCRIPTIONS_ANNOUNCER
212 | endpoint_flag::SUBSCRIPTIONS_DETECTOR;
213 let c = PeerCapabilities::from_bits(mask);
214 assert!(c.has_spdp);
215 assert!(c.has_sedp_publications);
216 assert!(c.has_sedp_subscriptions);
217 assert!(!c.has_wlp);
218 assert!(!c.has_topics_discovery);
219 assert!(!c.supports_security());
220 assert!(!c.fully_standard()); }
222
223 #[test]
224 fn capabilities_raw_is_preserved() {
225 let mask = 0xDEAD_BEEF & 0x3FFF_FFFFu32; let c = PeerCapabilities::from_bits(mask);
227 assert_eq!(c.raw, mask);
228 }
229}