zerodds_types/dynamic/
builtin_types.rs1extern crate alloc;
42use alloc::boxed::Box;
43use alloc::string::String;
44
45use super::builder::DynamicTypeBuilder;
46use super::descriptor::{MemberDescriptor, TypeDescriptor, TypeKind};
47use super::error::DynamicError;
48use super::type_::DynamicType;
49
50pub const NAME_DDS_STRING: &str = "DDS::String";
52
53pub const NAME_DDS_KEYED_STRING: &str = "DDS::KeyedString";
55
56pub const NAME_DDS_BYTES: &str = "DDS::Bytes";
58
59pub const NAME_DDS_KEYED_BYTES: &str = "DDS::KeyedBytes";
61
62pub fn dds_string() -> Result<DynamicType, DynamicError> {
70 let mut desc = TypeDescriptor::structure(NAME_DDS_STRING);
71 desc.is_nested = true;
72 let mut builder = DynamicTypeBuilder::new(desc);
73 builder.add_member(MemberDescriptor::new("value", 1, unbounded_string()))?;
74 builder.build()
75}
76
77fn unbounded_string() -> TypeDescriptor {
78 let mut t = TypeDescriptor::primitive(TypeKind::String8, "string");
79 t.bound = alloc::vec![0];
81 t
82}
83
84fn unbounded_octet_sequence() -> TypeDescriptor {
85 let mut t = TypeDescriptor::primitive(TypeKind::Sequence, "sequence");
86 t.bound = alloc::vec![0];
87 t.element_type = Some(Box::new(TypeDescriptor::primitive(TypeKind::Byte, "octet")));
88 t
89}
90
91pub fn dds_keyed_string() -> Result<DynamicType, DynamicError> {
98 let mut desc = TypeDescriptor::structure(NAME_DDS_KEYED_STRING);
99 desc.is_nested = true;
100 let mut builder = DynamicTypeBuilder::new(desc);
101 let mut key = MemberDescriptor::new("key", 1, unbounded_string());
102 key.is_key = true;
103 builder.add_member(key)?;
104 builder.add_member(MemberDescriptor::new("value", 2, unbounded_string()))?;
105 builder.build()
106}
107
108pub fn dds_bytes() -> Result<DynamicType, DynamicError> {
115 let mut desc = TypeDescriptor::structure(NAME_DDS_BYTES);
116 desc.is_nested = true;
117 let mut builder = DynamicTypeBuilder::new(desc);
118 builder.add_member(MemberDescriptor::new(
119 "value",
120 1,
121 unbounded_octet_sequence(),
122 ))?;
123 builder.build()
124}
125
126pub fn dds_keyed_bytes() -> Result<DynamicType, DynamicError> {
133 let mut desc = TypeDescriptor::structure(NAME_DDS_KEYED_BYTES);
134 desc.is_nested = true;
135 let mut builder = DynamicTypeBuilder::new(desc);
136 let mut key = MemberDescriptor::new("key", 1, unbounded_string());
137 key.is_key = true;
138 builder.add_member(key)?;
139 builder.add_member(MemberDescriptor::new(
140 "value",
141 2,
142 unbounded_octet_sequence(),
143 ))?;
144 builder.build()
145}
146
147pub fn all_builtin_types() -> Result<[(String, DynamicType); 4], DynamicError> {
154 Ok([
155 (String::from(NAME_DDS_STRING), dds_string()?),
156 (String::from(NAME_DDS_KEYED_STRING), dds_keyed_string()?),
157 (String::from(NAME_DDS_BYTES), dds_bytes()?),
158 (String::from(NAME_DDS_KEYED_BYTES), dds_keyed_bytes()?),
159 ])
160}
161
162#[must_use]
164pub fn is_builtin_type_name(name: &str) -> bool {
165 matches!(
166 name,
167 NAME_DDS_STRING | NAME_DDS_KEYED_STRING | NAME_DDS_BYTES | NAME_DDS_KEYED_BYTES
168 )
169}
170
171#[cfg(test)]
172#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn spec_names_match_annex_e() {
178 assert_eq!(NAME_DDS_STRING, "DDS::String");
181 assert_eq!(NAME_DDS_KEYED_STRING, "DDS::KeyedString");
182 assert_eq!(NAME_DDS_BYTES, "DDS::Bytes");
183 assert_eq!(NAME_DDS_KEYED_BYTES, "DDS::KeyedBytes");
184 }
185
186 #[test]
187 fn dds_string_has_one_value_member() {
188 let t = dds_string().unwrap();
189 assert_eq!(t.name(), NAME_DDS_STRING);
190 assert_eq!(t.kind(), TypeKind::Structure);
191 assert_eq!(t.member_count(), 1);
192 let member = t.member_by_name("value").unwrap();
193 assert_eq!(member.dynamic_type().kind(), TypeKind::String8);
194 assert!(!member.descriptor().is_key);
195 assert!(t.descriptor().is_nested);
196 }
197
198 #[test]
199 fn dds_keyed_string_has_key_and_value() {
200 let t = dds_keyed_string().unwrap();
201 assert_eq!(t.name(), NAME_DDS_KEYED_STRING);
202 assert_eq!(t.member_count(), 2);
203 let key = t.member_by_name("key").unwrap();
204 assert!(key.descriptor().is_key);
205 assert_eq!(key.dynamic_type().kind(), TypeKind::String8);
206 let value = t.member_by_name("value").unwrap();
207 assert!(!value.descriptor().is_key);
208 assert_eq!(value.dynamic_type().kind(), TypeKind::String8);
209 }
210
211 #[test]
212 fn dds_bytes_has_unbounded_octet_sequence() {
213 let t = dds_bytes().unwrap();
214 assert_eq!(t.name(), NAME_DDS_BYTES);
215 assert_eq!(t.member_count(), 1);
216 let value = t.member_by_name("value").unwrap();
217 assert_eq!(value.dynamic_type().kind(), TypeKind::Sequence);
218 assert_eq!(value.dynamic_type().descriptor().bound, alloc::vec![0]);
220 }
221
222 #[test]
223 fn dds_keyed_bytes_has_key_and_octet_sequence() {
224 let t = dds_keyed_bytes().unwrap();
225 assert_eq!(t.name(), NAME_DDS_KEYED_BYTES);
226 assert_eq!(t.member_count(), 2);
227 assert!(t.member_by_name("key").unwrap().descriptor().is_key);
228 assert_eq!(
229 t.member_by_name("value").unwrap().dynamic_type().kind(),
230 TypeKind::Sequence
231 );
232 }
233
234 #[test]
235 fn all_builtin_types_returns_four_with_correct_names() {
236 let types = all_builtin_types().unwrap();
237 let names: alloc::vec::Vec<_> = types.iter().map(|(n, _)| n.as_str()).collect();
238 assert_eq!(
239 names,
240 [
241 "DDS::String",
242 "DDS::KeyedString",
243 "DDS::Bytes",
244 "DDS::KeyedBytes"
245 ]
246 );
247 }
248
249 #[test]
250 fn is_builtin_type_name_recognises_all_four() {
251 assert!(is_builtin_type_name("DDS::String"));
252 assert!(is_builtin_type_name("DDS::KeyedString"));
253 assert!(is_builtin_type_name("DDS::Bytes"));
254 assert!(is_builtin_type_name("DDS::KeyedBytes"));
255 assert!(!is_builtin_type_name("dds::string"));
256 assert!(!is_builtin_type_name("MyApp::Custom"));
257 }
258
259 #[test]
260 fn all_builtin_types_have_nested_annotation() {
261 for (name, t) in all_builtin_types().unwrap() {
264 assert!(
265 t.descriptor().is_nested,
266 "{name} should have is_nested=true"
267 );
268 }
269 }
270
271 #[test]
272 fn dds_string_singleton_calls_produce_equal_types() {
273 let a = dds_string().unwrap();
275 let b = dds_string().unwrap();
276 assert!(a.equals(&b));
277 }
278
279 #[test]
280 fn keyed_types_have_exactly_one_key_member() {
281 for (name, t) in [
282 (NAME_DDS_KEYED_STRING, dds_keyed_string().unwrap()),
283 (NAME_DDS_KEYED_BYTES, dds_keyed_bytes().unwrap()),
284 ] {
285 let key_count = (0..t.member_count())
286 .filter_map(|i| t.member_by_index(i))
287 .filter(|m| m.descriptor().is_key)
288 .count();
289 assert_eq!(key_count, 1, "{name}: expected exactly 1 key member");
290 }
291 }
292
293 #[test]
294 fn unkeyed_types_have_no_key_member() {
295 for (name, t) in [
296 (NAME_DDS_STRING, dds_string().unwrap()),
297 (NAME_DDS_BYTES, dds_bytes().unwrap()),
298 ] {
299 let key_count = (0..t.member_count())
300 .filter_map(|i| t.member_by_index(i))
301 .filter(|m| m.descriptor().is_key)
302 .count();
303 assert_eq!(key_count, 0, "{name}: expected no key members");
304 }
305 }
306}