1use crate::DDS::XTypes as xt;
2use crate::XidlTypeObject;
3use std::any::TypeId;
4use std::cell::RefCell;
5use xidl_xcdr::xcdr2::Xcdr2Serialize;
6
7thread_local! {
8 static TYPE_STACK: RefCell<Vec<TypeId>> = const{ RefCell::new(Vec::new()) };
9}
10
11#[derive(Clone, Copy, Debug)]
12pub enum TypeEquivalence {
13 Minimal,
14 Complete,
15}
16
17pub struct StructMemberDesc<'a> {
18 pub member_id: u32,
19 pub member_flags: u32,
20 pub type_id: xt::TypeIdentifier,
21 pub name: &'a str,
22}
23
24pub struct UnionMemberDesc<'a> {
25 pub member_id: u32,
26 pub member_flags: u32,
27 pub type_id: xt::TypeIdentifier,
28 pub name: &'a str,
29 pub labels: Vec<i32>,
30}
31
32pub struct EnumLiteralDesc<'a> {
33 pub value: i32,
34 pub flags: u32,
35 pub name: &'a str,
36}
37
38pub struct BitflagDesc<'a> {
39 pub position: u16,
40 pub flags: u32,
41 pub name: &'a str,
42}
43
44pub struct BitfieldDesc<'a> {
45 pub position: u16,
46 pub flags: u32,
47 pub bitcount: u8,
48 pub holder_type: xt::TypeKind,
49 pub name: Option<&'a str>,
50}
51
52pub fn name_hash(name: &str) -> [u8; 4] {
53 let digest = md5::compute(name.as_bytes()).0;
54 let mut out = [0u8; 4];
55 out.copy_from_slice(&digest[..4]);
56 out
57}
58
59pub fn type_identifier_for<T: XidlTypeObject + 'static>(eq: TypeEquivalence) -> xt::TypeIdentifier {
60 let type_id = TypeId::of::<T>();
61 let reentrant = TYPE_STACK.with(|stack| stack.borrow().contains(&type_id));
62 if reentrant {
63 return type_identifier_none();
64 }
65 TYPE_STACK.with(|stack| stack.borrow_mut().push(type_id));
66 let object = match eq {
67 TypeEquivalence::Minimal => T::minimal_type_object(),
68 TypeEquivalence::Complete => T::complete_type_object(),
69 };
70 let hash = match eq {
71 TypeEquivalence::Minimal => {
72 let value = object
73 .minimal
74 .as_ref()
75 .expect("minimal type object missing");
76 hash_minimal_type_object(value.as_ref())
77 }
78 TypeEquivalence::Complete => {
79 let value = object
80 .complete
81 .as_ref()
82 .expect("complete type object missing");
83 hash_complete_type_object(value.as_ref())
84 }
85 };
86 let out = type_identifier_hash(
87 match eq {
88 TypeEquivalence::Minimal => xt::EK_MINIMAL,
89 TypeEquivalence::Complete => xt::EK_COMPLETE,
90 },
91 hash,
92 );
93 TYPE_STACK.with(|stack| {
94 let mut stack = stack.borrow_mut();
95 let _ = stack.pop();
96 });
97 out
98}
99
100pub fn type_identifier_none() -> xt::TypeIdentifier {
101 xt::TypeIdentifier {
102 _d: xt::TK_NONE,
103 string_sdefn: None,
104 string_ldefn: None,
105 seq_sdefn: None,
106 seq_ldefn: None,
107 array_sdefn: None,
108 array_ldefn: None,
109 map_sdefn: None,
110 map_ldefn: None,
111 sc_component_id: None,
112 equivalence_hash: None,
113 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
114 }
115}
116
117pub fn type_identifier_primitive(kind: xt::TypeKind) -> xt::TypeIdentifier {
118 xt::TypeIdentifier {
119 _d: kind,
120 string_sdefn: None,
121 string_ldefn: None,
122 seq_sdefn: None,
123 seq_ldefn: None,
124 array_sdefn: None,
125 array_ldefn: None,
126 map_sdefn: None,
127 map_ldefn: None,
128 sc_component_id: None,
129 equivalence_hash: None,
130 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
131 }
132}
133
134pub fn type_identifier_string(bound: Option<u32>, wide: bool) -> xt::TypeIdentifier {
135 let bound = bound.unwrap_or(0);
136 let (small, large) = if wide {
137 (xt::TI_STRING16_SMALL, xt::TI_STRING16_LARGE)
138 } else {
139 (xt::TI_STRING8_SMALL, xt::TI_STRING8_LARGE)
140 };
141 if bound <= u8::MAX as u32 {
142 xt::TypeIdentifier {
143 _d: small,
144 string_sdefn: Some(Box::new(xt::StringSTypeDefn {
145 bound: Box::new(bound as u8),
146 })),
147 string_ldefn: None,
148 seq_sdefn: None,
149 seq_ldefn: None,
150 array_sdefn: None,
151 array_ldefn: None,
152 map_sdefn: None,
153 map_ldefn: None,
154 sc_component_id: None,
155 equivalence_hash: None,
156 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
157 }
158 } else {
159 xt::TypeIdentifier {
160 _d: large,
161 string_sdefn: None,
162 string_ldefn: Some(Box::new(xt::StringLTypeDefn {
163 bound: Box::new(bound),
164 })),
165 seq_sdefn: None,
166 seq_ldefn: None,
167 array_sdefn: None,
168 array_ldefn: None,
169 map_sdefn: None,
170 map_ldefn: None,
171 sc_component_id: None,
172 equivalence_hash: None,
173 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
174 }
175 }
176}
177
178pub fn type_identifier_sequence(
179 element_id: xt::TypeIdentifier,
180 bound: u32,
181 eq: TypeEquivalence,
182) -> xt::TypeIdentifier {
183 let equiv_kind = if is_fully_descriptive(&element_id) {
184 xt::EK_BOTH
185 } else {
186 match eq {
187 TypeEquivalence::Complete => xt::EK_COMPLETE,
188 TypeEquivalence::Minimal => xt::EK_MINIMAL,
189 }
190 };
191 if bound <= u8::MAX as u32 {
192 xt::TypeIdentifier {
193 _d: xt::TI_PLAIN_SEQUENCE_SMALL,
194 string_sdefn: None,
195 string_ldefn: None,
196 seq_sdefn: Some(Box::new(xt::PlainSequenceSElemDefn {
197 header: Box::new(xt::PlainCollectionHeader {
198 equiv_kind: Box::new(equiv_kind),
199 element_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
200 }),
201 bound: Box::new(bound as u8),
202 element_identifier: Box::new(element_id),
203 })),
204 seq_ldefn: None,
205 array_sdefn: None,
206 array_ldefn: None,
207 map_sdefn: None,
208 map_ldefn: None,
209 sc_component_id: None,
210 equivalence_hash: None,
211 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
212 }
213 } else {
214 xt::TypeIdentifier {
215 _d: xt::TI_PLAIN_SEQUENCE_LARGE,
216 string_sdefn: None,
217 string_ldefn: None,
218 seq_sdefn: None,
219 seq_ldefn: Some(Box::new(xt::PlainSequenceLElemDefn {
220 header: Box::new(xt::PlainCollectionHeader {
221 equiv_kind: Box::new(equiv_kind),
222 element_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
223 }),
224 bound: Box::new(bound),
225 element_identifier: Box::new(element_id),
226 })),
227 array_sdefn: None,
228 array_ldefn: None,
229 map_sdefn: None,
230 map_ldefn: None,
231 sc_component_id: None,
232 equivalence_hash: None,
233 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
234 }
235 }
236}
237
238pub fn type_identifier_array(
239 element_id: xt::TypeIdentifier,
240 dims: &[u32],
241 eq: TypeEquivalence,
242) -> xt::TypeIdentifier {
243 let equiv_kind = if is_fully_descriptive(&element_id) {
244 xt::EK_BOTH
245 } else {
246 match eq {
247 TypeEquivalence::Complete => xt::EK_COMPLETE,
248 TypeEquivalence::Minimal => xt::EK_MINIMAL,
249 }
250 };
251 let use_small = dims.iter().all(|&dim| dim <= u8::MAX as u32);
252 if use_small {
253 let bounds = dims.iter().map(|&dim| dim as u8).collect::<Vec<_>>();
254 xt::TypeIdentifier {
255 _d: xt::TI_PLAIN_ARRAY_SMALL,
256 string_sdefn: None,
257 string_ldefn: None,
258 seq_sdefn: None,
259 seq_ldefn: None,
260 array_sdefn: Some(Box::new(xt::PlainArraySElemDefn {
261 header: Box::new(xt::PlainCollectionHeader {
262 equiv_kind: Box::new(equiv_kind),
263 element_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
264 }),
265 array_bound_seq: Box::new(bounds),
266 element_identifier: Box::new(element_id),
267 })),
268 array_ldefn: None,
269 map_sdefn: None,
270 map_ldefn: None,
271 sc_component_id: None,
272 equivalence_hash: None,
273 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
274 }
275 } else {
276 xt::TypeIdentifier {
277 _d: xt::TI_PLAIN_ARRAY_LARGE,
278 string_sdefn: None,
279 string_ldefn: None,
280 seq_sdefn: None,
281 seq_ldefn: None,
282 array_sdefn: None,
283 array_ldefn: Some(Box::new(xt::PlainArrayLElemDefn {
284 header: Box::new(xt::PlainCollectionHeader {
285 equiv_kind: Box::new(equiv_kind),
286 element_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
287 }),
288 array_bound_seq: Box::new(dims.to_vec()),
289 element_identifier: Box::new(element_id),
290 })),
291 map_sdefn: None,
292 map_ldefn: None,
293 sc_component_id: None,
294 equivalence_hash: None,
295 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
296 }
297 }
298}
299
300pub fn type_identifier_map(
301 key_id: xt::TypeIdentifier,
302 element_id: xt::TypeIdentifier,
303 bound: u32,
304 eq: TypeEquivalence,
305) -> xt::TypeIdentifier {
306 let equiv_kind = if is_fully_descriptive(&key_id) && is_fully_descriptive(&element_id) {
307 xt::EK_BOTH
308 } else {
309 match eq {
310 TypeEquivalence::Complete => xt::EK_COMPLETE,
311 TypeEquivalence::Minimal => xt::EK_MINIMAL,
312 }
313 };
314 if bound <= u8::MAX as u32 {
315 xt::TypeIdentifier {
316 _d: xt::TI_PLAIN_MAP_SMALL,
317 string_sdefn: None,
318 string_ldefn: None,
319 seq_sdefn: None,
320 seq_ldefn: None,
321 array_sdefn: None,
322 array_ldefn: None,
323 map_sdefn: Some(Box::new(xt::PlainMapSTypeDefn {
324 header: Box::new(xt::PlainCollectionHeader {
325 equiv_kind: Box::new(equiv_kind),
326 element_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
327 }),
328 bound: Box::new(bound as u8),
329 element_identifier: Box::new(element_id),
330 key_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
331 key_identifier: Box::new(key_id),
332 })),
333 map_ldefn: None,
334 sc_component_id: None,
335 equivalence_hash: None,
336 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
337 }
338 } else {
339 xt::TypeIdentifier {
340 _d: xt::TI_PLAIN_MAP_LARGE,
341 string_sdefn: None,
342 string_ldefn: None,
343 seq_sdefn: None,
344 seq_ldefn: None,
345 array_sdefn: None,
346 array_ldefn: None,
347 map_sdefn: None,
348 map_ldefn: Some(Box::new(xt::PlainMapLTypeDefn {
349 header: Box::new(xt::PlainCollectionHeader {
350 equiv_kind: Box::new(equiv_kind),
351 element_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
352 }),
353 bound: Box::new(bound),
354 element_identifier: Box::new(element_id),
355 key_flags: Box::new(xt::CollectionElementFlag { value: 0 }),
356 key_identifier: Box::new(key_id),
357 })),
358 sc_component_id: None,
359 equivalence_hash: None,
360 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
361 }
362 }
363}
364
365pub fn build_complete_alias(
366 type_name: &str,
367 type_flags: u32,
368 related_type: xt::TypeIdentifier,
369) -> xt::TypeObject {
370 xt::TypeObject {
371 _d: xt::EK_COMPLETE,
372 complete: Some(Box::new(xt::CompleteTypeObject {
373 _d: xt::TK_ALIAS,
374 alias_type: Some(Box::new(xt::CompleteAliasType {
375 alias_flags: Box::new(xt::TypeFlag { value: type_flags }),
376 header: Box::new(xt::CompleteAliasHeader {
377 detail: Box::new(complete_type_detail(type_name)),
378 }),
379 body: Box::new(xt::CompleteAliasBody {
380 common: Box::new(xt::CommonAliasBody {
381 related_flags: Box::new(xt::MemberFlag { value: 0 }),
382 related_type: Box::new(related_type),
383 }),
384 ann_builtin: Box::new(empty_applied_builtin_member_annotations()),
385 ann_custom: Box::new(Vec::new()),
386 }),
387 })),
388 annotation_type: None,
389 struct_type: None,
390 union_type: None,
391 bitset_type: None,
392 sequence_type: None,
393 array_type: None,
394 map_type: None,
395 enumerated_type: None,
396 bitmask_type: None,
397 extended_type: None,
398 })),
399 minimal: None,
400 }
401}
402
403pub fn build_minimal_alias(type_flags: u32, related_type: xt::TypeIdentifier) -> xt::TypeObject {
404 xt::TypeObject {
405 _d: xt::EK_MINIMAL,
406 complete: None,
407 minimal: Some(Box::new(xt::MinimalTypeObject {
408 _d: xt::TK_ALIAS,
409 alias_type: Some(Box::new(xt::MinimalAliasType {
410 alias_flags: Box::new(xt::TypeFlag { value: type_flags }),
411 header: Box::new(xt::MinimalAliasHeader {}),
412 body: Box::new(xt::MinimalAliasBody {
413 common: Box::new(xt::CommonAliasBody {
414 related_flags: Box::new(xt::MemberFlag { value: 0 }),
415 related_type: Box::new(related_type),
416 }),
417 }),
418 })),
419 annotation_type: None,
420 struct_type: None,
421 union_type: None,
422 bitset_type: None,
423 sequence_type: None,
424 array_type: None,
425 map_type: None,
426 enumerated_type: None,
427 bitmask_type: None,
428 extended_type: None,
429 })),
430 }
431}
432
433pub fn build_complete_struct(
434 type_name: &str,
435 type_flags: u32,
436 base_type: xt::TypeIdentifier,
437 mut members: Vec<StructMemberDesc<'_>>,
438) -> xt::TypeObject {
439 members.sort_by_key(|member| member.member_id);
440 let members = members
441 .into_iter()
442 .map(|member| xt::CompleteStructMember {
443 common: Box::new(xt::CommonStructMember {
444 member_id: Box::new(member.member_id),
445 member_flags: Box::new(xt::MemberFlag {
446 value: member.member_flags,
447 }),
448 member_type_id: Box::new(member.type_id),
449 }),
450 detail: Box::new(complete_member_detail(member.name)),
451 })
452 .collect::<Vec<_>>();
453 xt::TypeObject {
454 _d: xt::EK_COMPLETE,
455 complete: Some(Box::new(xt::CompleteTypeObject {
456 _d: xt::TK_STRUCTURE,
457 alias_type: None,
458 annotation_type: None,
459 struct_type: Some(Box::new(xt::CompleteStructType {
460 struct_flags: Box::new(xt::TypeFlag { value: type_flags }),
461 header: Box::new(xt::CompleteStructHeader {
462 base_type: Box::new(base_type),
463 detail: Box::new(complete_type_detail(type_name)),
464 }),
465 member_seq: Box::new(members),
466 })),
467 union_type: None,
468 bitset_type: None,
469 sequence_type: None,
470 array_type: None,
471 map_type: None,
472 enumerated_type: None,
473 bitmask_type: None,
474 extended_type: None,
475 })),
476 minimal: None,
477 }
478}
479
480pub fn build_minimal_struct(
481 type_flags: u32,
482 base_type: xt::TypeIdentifier,
483 mut members: Vec<StructMemberDesc<'_>>,
484) -> xt::TypeObject {
485 members.sort_by_key(|member| member.member_id);
486 let members = members
487 .into_iter()
488 .map(|member| xt::MinimalStructMember {
489 common: Box::new(xt::CommonStructMember {
490 member_id: Box::new(member.member_id),
491 member_flags: Box::new(xt::MemberFlag {
492 value: member.member_flags,
493 }),
494 member_type_id: Box::new(member.type_id),
495 }),
496 detail: Box::new(xt::MinimalMemberDetail {
497 name_hash: Box::new(name_hash(member.name)),
498 }),
499 })
500 .collect::<Vec<_>>();
501 xt::TypeObject {
502 _d: xt::EK_MINIMAL,
503 complete: None,
504 minimal: Some(Box::new(xt::MinimalTypeObject {
505 _d: xt::TK_STRUCTURE,
506 alias_type: None,
507 annotation_type: None,
508 struct_type: Some(Box::new(xt::MinimalStructType {
509 struct_flags: Box::new(xt::TypeFlag { value: type_flags }),
510 header: Box::new(xt::MinimalStructHeader {
511 base_type: Box::new(base_type),
512 detail: Box::new(xt::MinimalTypeDetail {}),
513 }),
514 member_seq: Box::new(members),
515 })),
516 union_type: None,
517 bitset_type: None,
518 sequence_type: None,
519 array_type: None,
520 map_type: None,
521 enumerated_type: None,
522 bitmask_type: None,
523 extended_type: None,
524 })),
525 }
526}
527
528pub fn build_complete_union(
529 type_name: &str,
530 type_flags: u32,
531 discriminator_type: xt::TypeIdentifier,
532 mut members: Vec<UnionMemberDesc<'_>>,
533) -> xt::TypeObject {
534 members.sort_by_key(|member| member.member_id);
535 let members = members
536 .into_iter()
537 .map(|member| xt::CompleteUnionMember {
538 common: Box::new(xt::CommonUnionMember {
539 member_id: Box::new(member.member_id),
540 member_flags: Box::new(xt::UnionMemberFlag {
541 value: member.member_flags,
542 }),
543 type_id: Box::new(member.type_id),
544 label_seq: Box::new(member.labels),
545 }),
546 detail: Box::new(complete_member_detail(member.name)),
547 })
548 .collect::<Vec<_>>();
549 let discriminator = xt::CompleteDiscriminatorMember {
550 common: Box::new(xt::CommonDiscriminatorMember {
551 member_flags: Box::new(xt::UnionDiscriminatorFlag { value: 0 }),
552 type_id: Box::new(discriminator_type),
553 }),
554 ann_builtin: Box::new(empty_applied_builtin_type_annotations()),
555 ann_custom: Box::new(Vec::new()),
556 };
557 xt::TypeObject {
558 _d: xt::EK_COMPLETE,
559 complete: Some(Box::new(xt::CompleteTypeObject {
560 _d: xt::TK_UNION,
561 alias_type: None,
562 annotation_type: None,
563 struct_type: None,
564 union_type: Some(Box::new(xt::CompleteUnionType {
565 union_flags: Box::new(xt::UnionTypeFlag { value: type_flags }),
566 header: Box::new(xt::CompleteUnionHeader {
567 detail: Box::new(complete_type_detail(type_name)),
568 }),
569 discriminator: Box::new(discriminator),
570 member_seq: Box::new(members),
571 })),
572 bitset_type: None,
573 sequence_type: None,
574 array_type: None,
575 map_type: None,
576 enumerated_type: None,
577 bitmask_type: None,
578 extended_type: None,
579 })),
580 minimal: None,
581 }
582}
583
584pub fn build_minimal_union(
585 type_flags: u32,
586 discriminator_type: xt::TypeIdentifier,
587 mut members: Vec<UnionMemberDesc<'_>>,
588) -> xt::TypeObject {
589 members.sort_by_key(|member| member.member_id);
590 let members = members
591 .into_iter()
592 .map(|member| xt::MinimalUnionMember {
593 common: Box::new(xt::CommonUnionMember {
594 member_id: Box::new(member.member_id),
595 member_flags: Box::new(xt::UnionMemberFlag {
596 value: member.member_flags,
597 }),
598 type_id: Box::new(member.type_id),
599 label_seq: Box::new(member.labels),
600 }),
601 detail: Box::new(xt::MinimalMemberDetail {
602 name_hash: Box::new(name_hash(member.name)),
603 }),
604 })
605 .collect::<Vec<_>>();
606 let discriminator = xt::MinimalDiscriminatorMember {
607 common: Box::new(xt::CommonDiscriminatorMember {
608 member_flags: Box::new(xt::UnionDiscriminatorFlag { value: 0 }),
609 type_id: Box::new(discriminator_type),
610 }),
611 };
612 xt::TypeObject {
613 _d: xt::EK_MINIMAL,
614 complete: None,
615 minimal: Some(Box::new(xt::MinimalTypeObject {
616 _d: xt::TK_UNION,
617 alias_type: None,
618 annotation_type: None,
619 struct_type: None,
620 union_type: Some(Box::new(xt::MinimalUnionType {
621 union_flags: Box::new(xt::UnionTypeFlag { value: type_flags }),
622 header: Box::new(xt::MinimalUnionHeader {
623 detail: Box::new(xt::MinimalTypeDetail {}),
624 }),
625 discriminator: Box::new(discriminator),
626 member_seq: Box::new(members),
627 })),
628 bitset_type: None,
629 sequence_type: None,
630 array_type: None,
631 map_type: None,
632 enumerated_type: None,
633 bitmask_type: None,
634 extended_type: None,
635 })),
636 }
637}
638
639pub fn build_complete_enum(
640 type_name: &str,
641 type_flags: u32,
642 bit_bound: u16,
643 mut literals: Vec<EnumLiteralDesc<'_>>,
644) -> xt::TypeObject {
645 literals.sort_by_key(|literal| literal.value);
646 let literals = literals
647 .into_iter()
648 .map(|literal| xt::CompleteEnumeratedLiteral {
649 common: Box::new(xt::CommonEnumeratedLiteral {
650 value: literal.value,
651 flags: Box::new(xt::EnumeratedLiteralFlag {
652 value: literal.flags,
653 }),
654 }),
655 detail: Box::new(complete_member_detail(literal.name)),
656 })
657 .collect::<Vec<_>>();
658 let header = xt::CompleteEnumeratedHeader {
659 common: Box::new(xt::CommonEnumeratedHeader {
660 bit_bound: Box::new(bit_bound),
661 }),
662 detail: Box::new(complete_type_detail(type_name)),
663 };
664 xt::TypeObject {
665 _d: xt::EK_COMPLETE,
666 complete: Some(Box::new(xt::CompleteTypeObject {
667 _d: xt::TK_ENUM,
668 alias_type: None,
669 annotation_type: None,
670 struct_type: None,
671 union_type: None,
672 bitset_type: None,
673 sequence_type: None,
674 array_type: None,
675 map_type: None,
676 enumerated_type: Some(Box::new(xt::CompleteEnumeratedType {
677 enum_flags: Box::new(xt::EnumTypeFlag { value: type_flags }),
678 header: Box::new(header),
679 literal_seq: Box::new(literals),
680 })),
681 bitmask_type: None,
682 extended_type: None,
683 })),
684 minimal: None,
685 }
686}
687
688pub fn build_minimal_enum(
689 type_flags: u32,
690 bit_bound: u16,
691 mut literals: Vec<EnumLiteralDesc<'_>>,
692) -> xt::TypeObject {
693 literals.sort_by_key(|literal| literal.value);
694 let literals = literals
695 .into_iter()
696 .map(|literal| xt::MinimalEnumeratedLiteral {
697 common: Box::new(xt::CommonEnumeratedLiteral {
698 value: literal.value,
699 flags: Box::new(xt::EnumeratedLiteralFlag {
700 value: literal.flags,
701 }),
702 }),
703 detail: Box::new(xt::MinimalMemberDetail {
704 name_hash: Box::new(name_hash(literal.name)),
705 }),
706 })
707 .collect::<Vec<_>>();
708 let header = xt::MinimalEnumeratedHeader {
709 common: Box::new(xt::CommonEnumeratedHeader {
710 bit_bound: Box::new(bit_bound),
711 }),
712 };
713 xt::TypeObject {
714 _d: xt::EK_MINIMAL,
715 complete: None,
716 minimal: Some(Box::new(xt::MinimalTypeObject {
717 _d: xt::TK_ENUM,
718 alias_type: None,
719 annotation_type: None,
720 struct_type: None,
721 union_type: None,
722 bitset_type: None,
723 sequence_type: None,
724 array_type: None,
725 map_type: None,
726 enumerated_type: Some(Box::new(xt::MinimalEnumeratedType {
727 enum_flags: Box::new(xt::EnumTypeFlag { value: type_flags }),
728 header: Box::new(header),
729 literal_seq: Box::new(literals),
730 })),
731 bitmask_type: None,
732 extended_type: None,
733 })),
734 }
735}
736
737pub fn build_complete_bitmask(
738 type_name: &str,
739 type_flags: u32,
740 bit_bound: u16,
741 mut flags: Vec<BitflagDesc<'_>>,
742) -> xt::TypeObject {
743 flags.sort_by_key(|flag| flag.position);
744 let flags = flags
745 .into_iter()
746 .map(|flag| xt::CompleteBitflag {
747 common: Box::new(xt::CommonBitflag {
748 position: flag.position,
749 flags: Box::new(xt::BitflagFlag { value: flag.flags }),
750 }),
751 detail: Box::new(complete_member_detail(flag.name)),
752 })
753 .collect::<Vec<_>>();
754 let header = xt::CompleteEnumeratedHeader {
755 common: Box::new(xt::CommonEnumeratedHeader {
756 bit_bound: Box::new(bit_bound),
757 }),
758 detail: Box::new(complete_type_detail(type_name)),
759 };
760 xt::TypeObject {
761 _d: xt::EK_COMPLETE,
762 complete: Some(Box::new(xt::CompleteTypeObject {
763 _d: xt::TK_BITMASK,
764 alias_type: None,
765 annotation_type: None,
766 struct_type: None,
767 union_type: None,
768 bitset_type: None,
769 sequence_type: None,
770 array_type: None,
771 map_type: None,
772 enumerated_type: None,
773 bitmask_type: Some(Box::new(xt::CompleteBitmaskType {
774 bitmask_flags: Box::new(xt::BitmaskTypeFlag { value: type_flags }),
775 header: Box::new(header),
776 flag_seq: Box::new(flags),
777 })),
778 extended_type: None,
779 })),
780 minimal: None,
781 }
782}
783
784pub fn build_minimal_bitmask(
785 type_flags: u32,
786 bit_bound: u16,
787 mut flags: Vec<BitflagDesc<'_>>,
788) -> xt::TypeObject {
789 flags.sort_by_key(|flag| flag.position);
790 let flags = flags
791 .into_iter()
792 .map(|flag| xt::MinimalBitflag {
793 common: Box::new(xt::CommonBitflag {
794 position: flag.position,
795 flags: Box::new(xt::BitflagFlag { value: flag.flags }),
796 }),
797 detail: Box::new(xt::MinimalMemberDetail {
798 name_hash: Box::new(name_hash(flag.name)),
799 }),
800 })
801 .collect::<Vec<_>>();
802 let header = xt::MinimalEnumeratedHeader {
803 common: Box::new(xt::CommonEnumeratedHeader {
804 bit_bound: Box::new(bit_bound),
805 }),
806 };
807 xt::TypeObject {
808 _d: xt::EK_MINIMAL,
809 complete: None,
810 minimal: Some(Box::new(xt::MinimalTypeObject {
811 _d: xt::TK_BITMASK,
812 alias_type: None,
813 annotation_type: None,
814 struct_type: None,
815 union_type: None,
816 bitset_type: None,
817 sequence_type: None,
818 array_type: None,
819 map_type: None,
820 enumerated_type: None,
821 bitmask_type: Some(Box::new(xt::MinimalBitmaskType {
822 bitmask_flags: Box::new(xt::BitmaskTypeFlag { value: type_flags }),
823 header: Box::new(header),
824 flag_seq: Box::new(flags),
825 })),
826 extended_type: None,
827 })),
828 }
829}
830
831pub fn build_complete_bitset(
832 type_name: &str,
833 type_flags: u32,
834 mut fields: Vec<BitfieldDesc<'_>>,
835) -> xt::TypeObject {
836 fields.sort_by_key(|field| field.position);
837 let fields = fields
838 .into_iter()
839 .map(|field| xt::CompleteBitfield {
840 common: Box::new(xt::CommonBitfield {
841 position: field.position,
842 flags: Box::new(xt::BitsetMemberFlag { value: field.flags }),
843 bitcount: field.bitcount,
844 holder_type: Box::new(field.holder_type),
845 }),
846 detail: Box::new(complete_member_detail(field.name.unwrap_or(""))),
847 })
848 .collect::<Vec<_>>();
849 xt::TypeObject {
850 _d: xt::EK_COMPLETE,
851 complete: Some(Box::new(xt::CompleteTypeObject {
852 _d: xt::TK_BITSET,
853 alias_type: None,
854 annotation_type: None,
855 struct_type: None,
856 union_type: None,
857 bitset_type: Some(Box::new(xt::CompleteBitsetType {
858 bitset_flags: Box::new(xt::BitsetTypeFlag { value: type_flags }),
859 header: Box::new(xt::CompleteBitsetHeader {
860 detail: Box::new(complete_type_detail(type_name)),
861 }),
862 field_seq: Box::new(fields),
863 })),
864 sequence_type: None,
865 array_type: None,
866 map_type: None,
867 enumerated_type: None,
868 bitmask_type: None,
869 extended_type: None,
870 })),
871 minimal: None,
872 }
873}
874
875pub fn build_minimal_bitset(type_flags: u32, mut fields: Vec<BitfieldDesc<'_>>) -> xt::TypeObject {
876 fields.sort_by_key(|field| field.position);
877 let fields = fields
878 .into_iter()
879 .map(|field| xt::MinimalBitfield {
880 common: Box::new(xt::CommonBitfield {
881 position: field.position,
882 flags: Box::new(xt::BitsetMemberFlag { value: field.flags }),
883 bitcount: field.bitcount,
884 holder_type: Box::new(field.holder_type),
885 }),
886 name_hash: Box::new(field.name.map(name_hash).unwrap_or([0u8; 4])),
887 })
888 .collect::<Vec<_>>();
889 xt::TypeObject {
890 _d: xt::EK_MINIMAL,
891 complete: None,
892 minimal: Some(Box::new(xt::MinimalTypeObject {
893 _d: xt::TK_BITSET,
894 alias_type: None,
895 annotation_type: None,
896 struct_type: None,
897 union_type: None,
898 bitset_type: Some(Box::new(xt::MinimalBitsetType {
899 bitset_flags: Box::new(xt::BitsetTypeFlag { value: type_flags }),
900 header: Box::new(xt::MinimalBitsetHeader {}),
901 field_seq: Box::new(fields),
902 })),
903 sequence_type: None,
904 array_type: None,
905 map_type: None,
906 enumerated_type: None,
907 bitmask_type: None,
908 extended_type: None,
909 })),
910 }
911}
912
913fn type_identifier_hash(discriminator: u8, hash: [u8; 14]) -> xt::TypeIdentifier {
914 xt::TypeIdentifier {
915 _d: discriminator,
916 string_sdefn: None,
917 string_ldefn: None,
918 seq_sdefn: None,
919 seq_ldefn: None,
920 array_sdefn: None,
921 array_ldefn: None,
922 map_sdefn: None,
923 map_ldefn: None,
924 sc_component_id: None,
925 equivalence_hash: Some(Box::new(hash)),
926 extended_defn: Some(Box::new(xt::ExtendedTypeDefn {})),
927 }
928}
929
930fn is_fully_descriptive(id: &xt::TypeIdentifier) -> bool {
931 match id._d {
932 xt::TK_BOOLEAN
933 | xt::TK_BYTE
934 | xt::TK_INT16
935 | xt::TK_INT32
936 | xt::TK_INT64
937 | xt::TK_UINT16
938 | xt::TK_UINT32
939 | xt::TK_UINT64
940 | xt::TK_FLOAT32
941 | xt::TK_FLOAT64
942 | xt::TK_FLOAT128
943 | xt::TK_CHAR8
944 | xt::TK_CHAR16 => true,
945 xt::TI_STRING8_SMALL
946 | xt::TI_STRING8_LARGE
947 | xt::TI_STRING16_SMALL
948 | xt::TI_STRING16_LARGE => true,
949 xt::TI_PLAIN_SEQUENCE_SMALL | xt::TI_PLAIN_SEQUENCE_LARGE => {
950 if let Some(seq) = id.seq_sdefn.as_ref() {
951 *seq.header.equiv_kind == xt::EK_BOTH
952 } else if let Some(seq) = id.seq_ldefn.as_ref() {
953 *seq.header.equiv_kind == xt::EK_BOTH
954 } else {
955 false
956 }
957 }
958 xt::TI_PLAIN_ARRAY_SMALL | xt::TI_PLAIN_ARRAY_LARGE => {
959 if let Some(arr) = id.array_sdefn.as_ref() {
960 *arr.header.equiv_kind == xt::EK_BOTH
961 } else if let Some(arr) = id.array_ldefn.as_ref() {
962 *arr.header.equiv_kind == xt::EK_BOTH
963 } else {
964 false
965 }
966 }
967 xt::TI_PLAIN_MAP_SMALL | xt::TI_PLAIN_MAP_LARGE => {
968 if let Some(map) = id.map_sdefn.as_ref() {
969 *map.header.equiv_kind == xt::EK_BOTH
970 } else if let Some(map) = id.map_ldefn.as_ref() {
971 *map.header.equiv_kind == xt::EK_BOTH
972 } else {
973 false
974 }
975 }
976 _ => false,
977 }
978}
979
980fn complete_type_detail(name: &str) -> xt::CompleteTypeDetail {
981 xt::CompleteTypeDetail {
982 ann_builtin: Box::new(empty_applied_builtin_type_annotations()),
983 ann_custom: Box::new(Vec::new()),
984 type_name: Box::new(name.to_string()),
985 }
986}
987
988fn complete_member_detail(name: &str) -> xt::CompleteMemberDetail {
989 xt::CompleteMemberDetail {
990 name: Box::new(name.to_string()),
991 ann_builtin: Box::new(empty_applied_builtin_member_annotations()),
992 ann_custom: Box::new(Vec::new()),
993 }
994}
995
996fn empty_applied_builtin_type_annotations() -> xt::AppliedBuiltinTypeAnnotations {
997 xt::AppliedBuiltinTypeAnnotations {
998 verbatim: Box::new(empty_verbatim_annotation()),
999 }
1000}
1001
1002fn empty_applied_builtin_member_annotations() -> xt::AppliedBuiltinMemberAnnotations {
1003 xt::AppliedBuiltinMemberAnnotations {
1004 unit: String::new(),
1005 min: Box::new(empty_annotation_parameter_value()),
1006 max: Box::new(empty_annotation_parameter_value()),
1007 hash_id: String::new(),
1008 }
1009}
1010
1011fn empty_verbatim_annotation() -> xt::AppliedVerbatimAnnotation {
1012 xt::AppliedVerbatimAnnotation {
1013 placement: String::new(),
1014 language: String::new(),
1015 text: String::new(),
1016 }
1017}
1018
1019fn empty_annotation_parameter_value() -> xt::AnnotationParameterValue {
1020 xt::AnnotationParameterValue {
1021 _d: xt::TK_NONE,
1022 boolean_value: None,
1023 byte_value: None,
1024 int16_value: None,
1025 uint_16_value: None,
1026 int32_value: None,
1027 uint32_value: None,
1028 int64_value: None,
1029 uint64_value: None,
1030 float32_value: None,
1031 float64_value: None,
1032 float128_value: None,
1033 char_value: None,
1034 wchar_value: None,
1035 enumerated_value: None,
1036 string8_value: None,
1037 string16_value: None,
1038 extended_value: Some(Box::new(xt::ExtendedAnnotationParameterValue {})),
1039 }
1040}
1041
1042fn hash_complete_type_object(value: &xt::CompleteTypeObject) -> [u8; 14] {
1043 hash_xcdr2(value)
1044}
1045
1046fn hash_minimal_type_object(value: &xt::MinimalTypeObject) -> [u8; 14] {
1047 hash_xcdr2(value)
1048}
1049
1050fn hash_xcdr2<T: xidl_xcdr::XcdrSerialize>(value: &T) -> [u8; 14] {
1051 let bytes = serialize_xcdr2(value);
1052 let digest = md5::compute(&bytes).0;
1053 let mut out = [0u8; 14];
1054 out.copy_from_slice(&digest[..14]);
1055 out
1056}
1057
1058fn serialize_xcdr2<T: xidl_xcdr::XcdrSerialize>(value: &T) -> Vec<u8> {
1059 let mut size = 256usize;
1060 loop {
1061 let mut buf = vec![0u8; size];
1062 let mut serializer = Xcdr2Serialize::new(buf.as_mut_ptr(), buf.len());
1063 match value.serialize_with(&mut serializer) {
1064 Ok(()) => {
1065 buf.truncate(serializer.pos);
1066 return buf;
1067 }
1068 Err(xidl_xcdr::error::XcdrError::BufferOverflow) => {
1069 size = size.saturating_mul(2);
1070 if size == 0 {
1071 panic!("xcdr2 serialize: size overflow");
1072 }
1073 }
1074 Err(err) => {
1075 panic!("xcdr2 serialize: {err}");
1076 }
1077 }
1078 }
1079}