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