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}