Skip to main content

xidl_typeobject/
runtime.rs

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}