extern crate alloc;
use zerodds_rtps::participant_data::endpoint_flag;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct PeerCapabilities {
pub raw: u32,
pub has_spdp: bool,
pub has_sedp_publications: bool,
pub has_sedp_subscriptions: bool,
pub has_wlp: bool,
pub has_type_lookup: bool,
pub has_topics_discovery: bool,
pub has_secure_publications: bool,
pub has_secure_subscriptions: bool,
pub has_secure_wlp: bool,
pub has_stateless_auth: bool,
pub has_volatile_secure: bool,
pub has_secure_participant: bool,
}
impl PeerCapabilities {
#[must_use]
pub fn from_bits(raw: u32) -> Self {
let bit_pair_set = |a: u32, b: u32| -> bool { raw & a != 0 && raw & b != 0 };
Self {
raw,
has_spdp: bit_pair_set(
endpoint_flag::PARTICIPANT_ANNOUNCER,
endpoint_flag::PARTICIPANT_DETECTOR,
),
has_sedp_publications: bit_pair_set(
endpoint_flag::PUBLICATIONS_ANNOUNCER,
endpoint_flag::PUBLICATIONS_DETECTOR,
),
has_sedp_subscriptions: bit_pair_set(
endpoint_flag::SUBSCRIPTIONS_ANNOUNCER,
endpoint_flag::SUBSCRIPTIONS_DETECTOR,
),
has_wlp: bit_pair_set(
endpoint_flag::PARTICIPANT_MESSAGE_DATA_WRITER,
endpoint_flag::PARTICIPANT_MESSAGE_DATA_READER,
),
has_type_lookup: (raw & endpoint_flag::TYPE_LOOKUP_REQUEST != 0)
&& (raw & endpoint_flag::TYPE_LOOKUP_REPLY != 0),
has_topics_discovery: bit_pair_set(
endpoint_flag::TOPICS_ANNOUNCER,
endpoint_flag::TOPICS_DETECTOR,
),
has_secure_publications: bit_pair_set(
endpoint_flag::PUBLICATIONS_SECURE_WRITER,
endpoint_flag::PUBLICATIONS_SECURE_READER,
),
has_secure_subscriptions: bit_pair_set(
endpoint_flag::SUBSCRIPTIONS_SECURE_WRITER,
endpoint_flag::SUBSCRIPTIONS_SECURE_READER,
),
has_secure_wlp: bit_pair_set(
endpoint_flag::PARTICIPANT_MESSAGE_SECURE_WRITER,
endpoint_flag::PARTICIPANT_MESSAGE_SECURE_READER,
),
has_stateless_auth: bit_pair_set(
endpoint_flag::PARTICIPANT_STATELESS_MESSAGE_WRITER,
endpoint_flag::PARTICIPANT_STATELESS_MESSAGE_READER,
),
has_volatile_secure: bit_pair_set(
endpoint_flag::PARTICIPANT_VOLATILE_MESSAGE_SECURE_WRITER,
endpoint_flag::PARTICIPANT_VOLATILE_MESSAGE_SECURE_READER,
),
has_secure_participant: bit_pair_set(
endpoint_flag::PARTICIPANT_SECURE_WRITER,
endpoint_flag::PARTICIPANT_SECURE_READER,
),
}
}
#[must_use]
pub fn supports_security(&self) -> bool {
self.raw & endpoint_flag::ALL_SECURE != 0
}
#[must_use]
pub fn fully_standard(&self) -> bool {
self.raw & endpoint_flag::ALL_STANDARD == endpoint_flag::ALL_STANDARD
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capabilities_from_zero_bitmask_is_all_false() {
let c = PeerCapabilities::from_bits(0);
assert_eq!(c.raw, 0);
assert!(!c.has_spdp);
assert!(!c.has_sedp_publications);
assert!(!c.has_sedp_subscriptions);
assert!(!c.has_wlp);
assert!(!c.has_topics_discovery);
assert!(!c.supports_security());
assert!(!c.fully_standard());
}
#[test]
fn capabilities_full_standard_bundle() {
let c = PeerCapabilities::from_bits(endpoint_flag::ALL_STANDARD);
assert!(c.has_spdp);
assert!(c.has_sedp_publications);
assert!(c.has_sedp_subscriptions);
assert!(c.has_wlp);
assert!(!c.has_topics_discovery);
assert!(c.fully_standard());
assert!(!c.supports_security());
assert!(!c.has_secure_publications);
}
#[test]
fn capabilities_topics_discovery_when_explicitly_added() {
let mask = endpoint_flag::ALL_STANDARD
| endpoint_flag::TOPICS_ANNOUNCER
| endpoint_flag::TOPICS_DETECTOR;
let c = PeerCapabilities::from_bits(mask);
assert!(c.has_topics_discovery);
}
#[test]
fn capabilities_full_secure_bundle() {
let c = PeerCapabilities::from_bits(endpoint_flag::ALL_SECURE);
assert!(c.supports_security());
assert!(c.has_secure_publications);
assert!(c.has_secure_subscriptions);
assert!(c.has_secure_wlp);
assert!(c.has_stateless_auth);
assert!(c.has_volatile_secure);
assert!(c.has_secure_participant);
assert!(!c.has_spdp);
assert!(!c.has_wlp);
}
#[test]
fn capabilities_partial_pair_does_not_count() {
let c = PeerCapabilities::from_bits(endpoint_flag::PUBLICATIONS_ANNOUNCER);
assert!(!c.has_sedp_publications);
}
#[test]
fn capabilities_combined_standard_and_secure() {
let mask = endpoint_flag::ALL_STANDARD | endpoint_flag::ALL_SECURE;
let c = PeerCapabilities::from_bits(mask);
assert!(c.fully_standard());
assert!(c.supports_security());
assert!(c.has_wlp);
assert!(c.has_secure_wlp);
}
#[test]
fn capabilities_legacy_peer_only_spdp_sedp() {
let mask = endpoint_flag::PARTICIPANT_ANNOUNCER
| endpoint_flag::PARTICIPANT_DETECTOR
| endpoint_flag::PUBLICATIONS_ANNOUNCER
| endpoint_flag::PUBLICATIONS_DETECTOR
| endpoint_flag::SUBSCRIPTIONS_ANNOUNCER
| endpoint_flag::SUBSCRIPTIONS_DETECTOR;
let c = PeerCapabilities::from_bits(mask);
assert!(c.has_spdp);
assert!(c.has_sedp_publications);
assert!(c.has_sedp_subscriptions);
assert!(!c.has_wlp);
assert!(!c.has_topics_discovery);
assert!(!c.supports_security());
assert!(!c.fully_standard()); }
#[test]
fn capabilities_raw_is_preserved() {
let mask = 0xDEAD_BEEF & 0x3FFF_FFFFu32; let c = PeerCapabilities::from_bits(mask);
assert_eq!(c.raw, mask);
}
}