zerodds_rpc/
discovery_ext.rs1extern crate alloc;
20
21use alloc::string::String;
22use alloc::vec::Vec;
23
24#[derive(Debug, Clone, PartialEq, Eq, Default)]
26pub struct PublicationBuiltinTopicDataExt {
27 pub service_name: String,
29 pub mapping_profile: ServiceMappingProfile,
31 pub topic_aliases: Vec<String>,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Default)]
37pub struct SubscriptionBuiltinTopicDataExt {
38 pub service_name: String,
40 pub mapping_profile: ServiceMappingProfile,
42 pub topic_aliases: Vec<String>,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48pub enum ServiceMappingProfile {
49 #[default]
51 Basic,
52 Enhanced,
54}
55
56#[must_use]
62pub fn client_matches_service(
63 client_pub_data: &PublicationBuiltinTopicDataExt,
64 service_sub_data: &SubscriptionBuiltinTopicDataExt,
65) -> bool {
66 if client_pub_data.service_name != service_sub_data.service_name {
67 return false;
68 }
69 profile_compatible(
70 client_pub_data.mapping_profile,
71 service_sub_data.mapping_profile,
72 )
73}
74
75#[must_use]
77pub fn service_matches_client(
78 service_pub_data: &PublicationBuiltinTopicDataExt,
79 client_sub_data: &SubscriptionBuiltinTopicDataExt,
80) -> bool {
81 if service_pub_data.service_name != client_sub_data.service_name {
82 return false;
83 }
84 profile_compatible(
85 service_pub_data.mapping_profile,
86 client_sub_data.mapping_profile,
87 )
88}
89
90fn profile_compatible(a: ServiceMappingProfile, b: ServiceMappingProfile) -> bool {
94 a == b
95}
96
97#[cfg(test)]
98#[allow(clippy::expect_used)]
99mod tests {
100 use super::*;
101
102 fn pub_data(name: &str, profile: ServiceMappingProfile) -> PublicationBuiltinTopicDataExt {
103 PublicationBuiltinTopicDataExt {
104 service_name: name.into(),
105 mapping_profile: profile,
106 topic_aliases: Vec::new(),
107 }
108 }
109
110 fn sub_data(name: &str, profile: ServiceMappingProfile) -> SubscriptionBuiltinTopicDataExt {
111 SubscriptionBuiltinTopicDataExt {
112 service_name: name.into(),
113 mapping_profile: profile,
114 topic_aliases: Vec::new(),
115 }
116 }
117
118 #[test]
119 fn client_matches_service_with_same_name_and_profile() {
120 let p = pub_data("Calc", ServiceMappingProfile::Basic);
121 let s = sub_data("Calc", ServiceMappingProfile::Basic);
122 assert!(client_matches_service(&p, &s));
123 }
124
125 #[test]
126 fn client_does_not_match_service_with_different_name() {
127 let p = pub_data("Calc", ServiceMappingProfile::Basic);
128 let s = sub_data("Other", ServiceMappingProfile::Basic);
129 assert!(!client_matches_service(&p, &s));
130 }
131
132 #[test]
133 fn client_does_not_match_service_with_different_profile() {
134 let p = pub_data("Calc", ServiceMappingProfile::Basic);
136 let s = sub_data("Calc", ServiceMappingProfile::Enhanced);
137 assert!(!client_matches_service(&p, &s));
138 }
139
140 #[test]
141 fn service_matches_client_symmetric() {
142 let p = pub_data("Calc", ServiceMappingProfile::Enhanced);
143 let s = sub_data("Calc", ServiceMappingProfile::Enhanced);
144 assert!(service_matches_client(&p, &s));
145 }
146
147 #[test]
148 fn topic_aliases_propagated_in_extended_data() {
149 let p = PublicationBuiltinTopicDataExt {
150 service_name: "Inherited".into(),
151 mapping_profile: ServiceMappingProfile::Enhanced,
152 topic_aliases: alloc::vec!["BaseInterface_Request".into()],
153 };
154 assert_eq!(p.topic_aliases.len(), 1);
155 assert_eq!(p.topic_aliases[0], "BaseInterface_Request");
156 }
157}