1use alloc::format;
19use alloc::string::{String, ToString};
20use alloc::vec::Vec;
21
22use crate::type_identifier::{PrimitiveKind, TypeIdentifier};
23use crate::type_object::common::{CommonStructMember, CommonUnionMember};
24use crate::type_object::complete::{
25 CompleteAliasBody, CompleteAliasHeader, CompleteAliasType, CompleteAnnotationParameter,
26 CompleteAnnotationType, CompleteArrayType, CompleteBitfield, CompleteBitflag,
27 CompleteBitmaskType, CompleteBitsetType, CompleteCollectionElement,
28 CompleteDiscriminatorMember, CompleteEnumeratedHeader, CompleteEnumeratedLiteral,
29 CompleteEnumeratedType, CompleteMapType, CompleteSequenceType, CompleteStructHeader,
30 CompleteStructMember, CompleteStructType, CompleteUnionHeader, CompleteUnionMember,
31 CompleteUnionType,
32};
33use crate::type_object::flags::{
34 AliasMemberFlag, AliasTypeFlag, AnnotationParameterFlag, AnnotationTypeFlag, BitfieldFlag,
35 BitflagFlag, BitmaskTypeFlag, BitsetTypeFlag, CollectionElementFlag, CollectionTypeFlag,
36 EnumLiteralFlag, EnumTypeFlag, StructMemberFlag, StructTypeFlag, UnionDiscriminatorFlag,
37 UnionMemberFlag, UnionTypeFlag,
38};
39use crate::type_object::minimal::CommonDiscriminatorMember;
40use crate::type_object::minimal::{
41 CommonBitfield, CommonBitflag, CommonCollectionElement, CommonEnumeratedHeader,
42 CommonEnumeratedLiteral,
43};
44use crate::type_object::{CompleteTypeObject, TypeObject};
45
46use super::builder::{DynamicTypeBuilder, DynamicTypeBuilderFactory};
47use super::descriptor::{ExtensibilityKind, MemberDescriptor, TypeDescriptor, TypeKind};
48use super::error::DynamicError;
49use super::type_::DynamicType;
50
51impl DynamicType {
56 pub fn to_type_object(&self) -> Result<TypeObject, DynamicError> {
68 match self.kind() {
69 TypeKind::Structure => Ok(TypeObject::Complete(CompleteTypeObject::Struct(
70 self.to_complete_struct()?,
71 ))),
72 TypeKind::Union => Ok(TypeObject::Complete(CompleteTypeObject::Union(
73 self.to_complete_union()?,
74 ))),
75 TypeKind::Enumeration => Ok(TypeObject::Complete(CompleteTypeObject::Enumerated(
76 self.to_complete_enum()?,
77 ))),
78 TypeKind::Bitmask => Ok(TypeObject::Complete(CompleteTypeObject::Bitmask(
79 self.to_complete_bitmask()?,
80 ))),
81 TypeKind::Alias => Ok(TypeObject::Complete(CompleteTypeObject::Alias(
82 self.to_complete_alias()?,
83 ))),
84 TypeKind::Sequence => Ok(TypeObject::Complete(CompleteTypeObject::Sequence(
85 self.to_complete_sequence()?,
86 ))),
87 TypeKind::Array => Ok(TypeObject::Complete(CompleteTypeObject::Array(
88 self.to_complete_array()?,
89 ))),
90 TypeKind::Map => Ok(TypeObject::Complete(CompleteTypeObject::Map(
91 self.to_complete_map()?,
92 ))),
93 TypeKind::Bitset => Ok(TypeObject::Complete(CompleteTypeObject::Bitset(
94 self.to_complete_bitset()?,
95 ))),
96 TypeKind::Annotation => Ok(TypeObject::Complete(CompleteTypeObject::Annotation(
97 self.to_complete_annotation()?,
98 ))),
99 other => Err(DynamicError::unsupported(format!(
100 "to_type_object: {other:?} is a primitive/no-type kind without TypeObject",
101 ))),
102 }
103 }
104
105 fn to_complete_sequence(&self) -> Result<CompleteSequenceType, DynamicError> {
108 use crate::type_object::common::{
109 AppliedBuiltinTypeAnnotations, CompleteTypeDetail, OptionalAppliedAnnotationSeq,
110 };
111 let element = self
112 .descriptor()
113 .element_type
114 .as_ref()
115 .ok_or_else(|| DynamicError::inconsistent("sequence type missing element_type"))?;
116 let bound = self.descriptor().bound.first().copied().unwrap_or(0);
117 Ok(CompleteSequenceType {
118 collection_flag: CollectionTypeFlag(0),
119 bound,
120 detail: CompleteTypeDetail {
121 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
122 ann_custom: OptionalAppliedAnnotationSeq::default(),
123 type_name: self.descriptor().name.clone(),
124 },
125 element: complete_collection_element(element)?,
126 })
127 }
128
129 fn to_complete_array(&self) -> Result<CompleteArrayType, DynamicError> {
132 use crate::type_object::common::{
133 AppliedBuiltinTypeAnnotations, CompleteTypeDetail, OptionalAppliedAnnotationSeq,
134 };
135 let element = self
136 .descriptor()
137 .element_type
138 .as_ref()
139 .ok_or_else(|| DynamicError::inconsistent("array type missing element_type"))?;
140 let bound_seq = self.descriptor().bound.clone();
141 if bound_seq.is_empty() {
142 return Err(DynamicError::inconsistent(
143 "array type missing dimensions (bound)",
144 ));
145 }
146 Ok(CompleteArrayType {
147 collection_flag: CollectionTypeFlag(0),
148 bound_seq,
149 detail: CompleteTypeDetail {
150 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
151 ann_custom: OptionalAppliedAnnotationSeq::default(),
152 type_name: self.descriptor().name.clone(),
153 },
154 element: complete_collection_element(element)?,
155 })
156 }
157
158 fn to_complete_map(&self) -> Result<CompleteMapType, DynamicError> {
161 use crate::type_object::common::{
162 AppliedBuiltinTypeAnnotations, CompleteTypeDetail, OptionalAppliedAnnotationSeq,
163 };
164 let value =
165 self.descriptor().element_type.as_ref().ok_or_else(|| {
166 DynamicError::inconsistent("map type missing element_type (value)")
167 })?;
168 let key = self
169 .descriptor()
170 .key_element_type
171 .as_ref()
172 .ok_or_else(|| DynamicError::inconsistent("map type missing key_element_type"))?;
173 let bound = self.descriptor().bound.first().copied().unwrap_or(0);
174 Ok(CompleteMapType {
175 collection_flag: CollectionTypeFlag(0),
176 bound,
177 detail: CompleteTypeDetail {
178 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
179 ann_custom: OptionalAppliedAnnotationSeq::default(),
180 type_name: self.descriptor().name.clone(),
181 },
182 key: complete_collection_element(key)?,
183 element: complete_collection_element(value)?,
184 })
185 }
186
187 fn to_complete_alias(&self) -> Result<CompleteAliasType, DynamicError> {
188 use crate::type_object::common::{
189 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteTypeDetail,
190 OptionalAppliedAnnotationSeq,
191 };
192 let header = CompleteAliasHeader {
193 detail: CompleteTypeDetail {
194 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
195 ann_custom: OptionalAppliedAnnotationSeq::default(),
196 type_name: self.descriptor().name.clone(),
197 },
198 };
199 let element = self.descriptor().element_type.as_ref().ok_or_else(|| {
200 DynamicError::inconsistent("alias type missing element_type (target)")
201 })?;
202 let related_type = descriptor_to_type_identifier(element)?;
203 let body = CompleteAliasBody {
204 related_flags: AliasMemberFlag(0),
205 related_type,
206 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
207 ann_custom: OptionalAppliedAnnotationSeq::default(),
208 };
209 Ok(CompleteAliasType {
210 alias_flags: AliasTypeFlag(0),
211 header,
212 body,
213 })
214 }
215
216 fn to_complete_enum(&self) -> Result<CompleteEnumeratedType, DynamicError> {
217 use crate::type_object::common::{
218 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
219 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
220 };
221 let bit_bound = self.descriptor().bound.first().copied().unwrap_or(32);
222 let bit_bound_u16 = u16::try_from(bit_bound).unwrap_or(32);
223 let header = CompleteEnumeratedHeader {
224 common: CommonEnumeratedHeader {
225 bit_bound: bit_bound_u16,
226 },
227 detail: CompleteTypeDetail {
228 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
229 ann_custom: OptionalAppliedAnnotationSeq::default(),
230 type_name: self.descriptor().name.clone(),
231 },
232 };
233 let mut literal_seq: Vec<CompleteEnumeratedLiteral> =
234 Vec::with_capacity(self.member_count() as usize);
235 for m in self.members() {
236 let mut flags_bits: u16 = 0;
237 if m.descriptor().is_default_label {
238 flags_bits |= EnumLiteralFlag::IS_DEFAULT_LITERAL;
239 }
240 let value = i32::try_from(m.id()).map_err(|_| {
242 DynamicError::inconsistent(format!("enum literal id {} exceeds i32 range", m.id()))
243 })?;
244 literal_seq.push(CompleteEnumeratedLiteral {
245 common: CommonEnumeratedLiteral {
246 value,
247 flags: EnumLiteralFlag(flags_bits),
248 },
249 detail: CompleteMemberDetail {
250 name: m.name().to_string(),
251 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
252 ann_custom: OptionalAppliedAnnotationSeq::default(),
253 },
254 });
255 }
256 Ok(CompleteEnumeratedType {
257 enum_flags: EnumTypeFlag(0),
258 header,
259 literal_seq,
260 })
261 }
262
263 fn to_complete_bitmask(&self) -> Result<CompleteBitmaskType, DynamicError> {
264 use crate::type_object::common::{
265 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
266 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
267 };
268 let bit_bound = self.descriptor().bound.first().copied().unwrap_or(32);
269 let bit_bound_u16 = u16::try_from(bit_bound).unwrap_or(32);
270 let detail = CompleteTypeDetail {
271 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
272 ann_custom: OptionalAppliedAnnotationSeq::default(),
273 type_name: self.descriptor().name.clone(),
274 };
275 let mut flag_seq: Vec<CompleteBitflag> = Vec::with_capacity(self.member_count() as usize);
276 for m in self.members() {
277 let position = u16::try_from(m.id()).map_err(|_| {
278 DynamicError::inconsistent(format!(
279 "bitmask flag position {} exceeds u16 range",
280 m.id()
281 ))
282 })?;
283 flag_seq.push(CompleteBitflag {
284 common: CommonBitflag {
285 position,
286 flags: BitflagFlag(0),
287 },
288 detail: CompleteMemberDetail {
289 name: m.name().to_string(),
290 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
291 ann_custom: OptionalAppliedAnnotationSeq::default(),
292 },
293 });
294 }
295 Ok(CompleteBitmaskType {
296 bitmask_flags: BitmaskTypeFlag(0),
297 bit_bound: bit_bound_u16,
298 detail,
299 flag_seq,
300 })
301 }
302
303 fn to_complete_bitset(&self) -> Result<CompleteBitsetType, DynamicError> {
308 use crate::type_object::common::{
309 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
310 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
311 };
312 let detail = CompleteTypeDetail {
313 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
314 ann_custom: OptionalAppliedAnnotationSeq::default(),
315 type_name: self.descriptor().name.clone(),
316 };
317 let mut field_seq: Vec<CompleteBitfield> = Vec::with_capacity(self.member_count() as usize);
318 for m in self.members() {
319 let position = u16::try_from(m.id()).map_err(|_| {
320 DynamicError::inconsistent(format!(
321 "bitset field position {} exceeds u16 range",
322 m.id()
323 ))
324 })?;
325 let holder_type = match descriptor_to_type_identifier(
326 m.descriptor().member_type.as_ref(),
327 )? {
328 TypeIdentifier::Primitive(pk) => pk.to_u8(),
329 other => {
330 return Err(DynamicError::inconsistent(format!(
331 "bitset field {:?} holder must be a primitive integer type, got {other:?}",
332 m.name()
333 )));
334 }
335 };
336 let bitcount = m.descriptor().bit_bound.ok_or_else(|| {
337 DynamicError::inconsistent(format!(
338 "bitset field {:?} missing bit_bound (bitfield width)",
339 m.name()
340 ))
341 })?;
342 field_seq.push(CompleteBitfield {
343 common: CommonBitfield {
344 position,
345 flags: BitfieldFlag(0),
346 bitcount,
347 holder_type,
348 },
349 detail: CompleteMemberDetail {
350 name: m.name().to_string(),
351 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
352 ann_custom: OptionalAppliedAnnotationSeq::default(),
353 },
354 });
355 }
356 Ok(CompleteBitsetType {
357 bitset_flags: BitsetTypeFlag(0),
358 detail,
359 field_seq,
360 })
361 }
362
363 fn to_complete_annotation(&self) -> Result<CompleteAnnotationType, DynamicError> {
368 use crate::type_object::common::{
369 AppliedBuiltinTypeAnnotations, CompleteTypeDetail, OptionalAppliedAnnotationSeq,
370 };
371 let detail = CompleteTypeDetail {
372 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
373 ann_custom: OptionalAppliedAnnotationSeq::default(),
374 type_name: self.descriptor().name.clone(),
375 };
376 let mut member_seq: Vec<CompleteAnnotationParameter> =
377 Vec::with_capacity(self.member_count() as usize);
378 for m in self.members() {
379 let member_type_id =
380 descriptor_to_type_identifier(m.descriptor().member_type.as_ref())?;
381 let default_value = m
382 .descriptor()
383 .default_value
384 .as_deref()
385 .map(|s| s.as_bytes().to_vec())
386 .unwrap_or_default();
387 member_seq.push(CompleteAnnotationParameter {
388 member_id: m.id(),
389 member_flags: AnnotationParameterFlag(0),
390 member_type_id,
391 name: m.name().to_string(),
392 default_value,
393 });
394 }
395 Ok(CompleteAnnotationType {
396 annotation_flag: AnnotationTypeFlag(0),
397 detail,
398 member_seq,
399 })
400 }
401
402 fn to_complete_union(&self) -> Result<CompleteUnionType, DynamicError> {
403 use crate::type_object::common::{
404 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
405 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
406 };
407 let union_flags = UnionTypeFlag(extensibility_to_flag_bits(
408 self.descriptor().extensibility_kind,
409 ));
410 let header = CompleteUnionHeader {
411 detail: CompleteTypeDetail {
412 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
413 ann_custom: OptionalAppliedAnnotationSeq::default(),
414 type_name: self.descriptor().name.clone(),
415 },
416 };
417 let disc_descriptor = self
418 .descriptor()
419 .discriminator_type
420 .as_ref()
421 .ok_or_else(|| DynamicError::inconsistent("union type missing discriminator_type"))?;
422 let disc_type = descriptor_to_type_identifier(disc_descriptor)?;
423 let discriminator = CompleteDiscriminatorMember {
424 common: CommonDiscriminatorMember {
425 member_flags: UnionDiscriminatorFlag(0),
426 type_id: disc_type,
427 },
428 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
429 ann_custom: OptionalAppliedAnnotationSeq::default(),
430 };
431 let mut member_seq: Vec<CompleteUnionMember> =
432 Vec::with_capacity(self.member_count() as usize);
433 for m in self.members() {
434 let mut flags_bits: u16 = 0;
435 if m.descriptor().is_default_label {
436 flags_bits |= UnionMemberFlag::IS_DEFAULT;
437 }
438 let label_seq: Vec<i32> = m
440 .descriptor()
441 .label
442 .iter()
443 .map(|&v| i32::try_from(v).unwrap_or_default())
444 .collect();
445 let common = CommonUnionMember {
446 member_id: m.id(),
447 member_flags: UnionMemberFlag(flags_bits),
448 type_id: descriptor_to_type_identifier(m.descriptor().member_type.as_ref())?,
449 label_seq,
450 };
451 let detail = CompleteMemberDetail {
452 name: m.name().to_string(),
453 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
454 ann_custom: OptionalAppliedAnnotationSeq::default(),
455 };
456 member_seq.push(CompleteUnionMember { common, detail });
457 }
458 Ok(CompleteUnionType {
459 union_flags,
460 header,
461 discriminator,
462 member_seq,
463 })
464 }
465
466 fn to_complete_struct(&self) -> Result<CompleteStructType, DynamicError> {
467 use crate::type_object::common::{
468 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
469 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
470 };
471 let struct_flags = StructTypeFlag(extensibility_to_flag_bits(
472 self.descriptor().extensibility_kind,
473 ));
474 let header = CompleteStructHeader {
475 base_type: TypeIdentifier::None,
476 detail: CompleteTypeDetail {
477 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
478 ann_custom: OptionalAppliedAnnotationSeq::default(),
479 type_name: self.descriptor().name.clone(),
480 },
481 };
482 let mut member_seq: Vec<CompleteStructMember> =
483 Vec::with_capacity(self.member_count() as usize);
484 for m in self.members() {
485 let mut flags_bits: u16 = 0;
486 if m.descriptor().is_key {
487 flags_bits |= StructMemberFlag::IS_KEY;
488 }
489 if m.descriptor().is_optional {
490 flags_bits |= StructMemberFlag::IS_OPTIONAL;
491 }
492 if m.descriptor().is_must_understand {
493 flags_bits |= StructMemberFlag::IS_MUST_UNDERSTAND;
494 }
495 if m.descriptor().is_shared {
496 flags_bits |= StructMemberFlag::IS_EXTERNAL;
497 }
498 let common = CommonStructMember {
499 member_id: m.id(),
500 member_flags: StructMemberFlag(flags_bits),
501 member_type_id: descriptor_to_type_identifier(m.descriptor().member_type.as_ref())?,
502 };
503 let detail = CompleteMemberDetail {
504 name: m.name().to_string(),
505 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
506 ann_custom: OptionalAppliedAnnotationSeq::default(),
507 };
508 member_seq.push(CompleteStructMember { common, detail });
509 }
510 Ok(CompleteStructType {
511 struct_flags,
512 header,
513 member_seq,
514 })
515 }
516}
517
518const fn extensibility_to_flag_bits(ext: ExtensibilityKind) -> u16 {
519 match ext {
520 ExtensibilityKind::Final => StructTypeFlag::IS_FINAL,
521 ExtensibilityKind::Appendable => StructTypeFlag::IS_APPENDABLE,
522 ExtensibilityKind::Mutable => StructTypeFlag::IS_MUTABLE,
523 }
524}
525
526const fn flag_bits_to_extensibility(flags: u16) -> ExtensibilityKind {
527 if flags & StructTypeFlag::IS_FINAL != 0 {
528 ExtensibilityKind::Final
529 } else if flags & StructTypeFlag::IS_MUTABLE != 0 {
530 ExtensibilityKind::Mutable
531 } else {
532 ExtensibilityKind::Appendable
533 }
534}
535
536fn complete_collection_element(
539 desc: &TypeDescriptor,
540) -> Result<CompleteCollectionElement, DynamicError> {
541 use crate::type_object::common::{
542 AppliedBuiltinMemberAnnotations, OptionalAppliedAnnotationSeq,
543 };
544 Ok(CompleteCollectionElement {
545 common: CommonCollectionElement {
546 element_flags: CollectionElementFlag(0),
547 type_id: descriptor_to_type_identifier(desc)?,
548 },
549 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
550 ann_custom: OptionalAppliedAnnotationSeq::default(),
551 })
552}
553
554fn descriptor_to_type_identifier(desc: &TypeDescriptor) -> Result<TypeIdentifier, DynamicError> {
559 match desc.kind {
560 TypeKind::Boolean => Ok(TypeIdentifier::Primitive(PrimitiveKind::Boolean)),
561 TypeKind::Byte => Ok(TypeIdentifier::Primitive(PrimitiveKind::Byte)),
562 TypeKind::Int8 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Int8)),
563 TypeKind::UInt8 => Ok(TypeIdentifier::Primitive(PrimitiveKind::UInt8)),
564 TypeKind::Int16 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Int16)),
565 TypeKind::UInt16 => Ok(TypeIdentifier::Primitive(PrimitiveKind::UInt16)),
566 TypeKind::Int32 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Int32)),
567 TypeKind::UInt32 => Ok(TypeIdentifier::Primitive(PrimitiveKind::UInt32)),
568 TypeKind::Int64 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Int64)),
569 TypeKind::UInt64 => Ok(TypeIdentifier::Primitive(PrimitiveKind::UInt64)),
570 TypeKind::Float32 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Float32)),
571 TypeKind::Float64 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Float64)),
572 TypeKind::Float128 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Float128)),
573 TypeKind::Char8 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Char8)),
574 TypeKind::Char16 => Ok(TypeIdentifier::Primitive(PrimitiveKind::Char16)),
575 TypeKind::String8 => {
576 let bound = desc.bound.first().copied().unwrap_or(0);
577 if bound <= u32::from(u8::MAX) {
578 Ok(TypeIdentifier::String8Small { bound: bound as u8 })
579 } else {
580 Ok(TypeIdentifier::String8Large { bound })
581 }
582 }
583 TypeKind::String16 => {
584 let bound = desc.bound.first().copied().unwrap_or(0);
585 if bound <= u32::from(u8::MAX) {
586 Ok(TypeIdentifier::String16Small { bound: bound as u8 })
587 } else {
588 Ok(TypeIdentifier::String16Large { bound })
589 }
590 }
591 TypeKind::Structure | TypeKind::Union | TypeKind::Enumeration | TypeKind::Alias => {
592 Ok(TypeIdentifier::None)
597 }
598 kind => Err(DynamicError::unsupported(format!(
599 "descriptor_to_type_identifier: {kind:?} not yet covered"
600 ))),
601 }
602}
603
604impl DynamicTypeBuilderFactory {
609 pub fn create_type_w_type_object(
619 type_obj: &TypeObject,
620 ) -> Result<DynamicTypeBuilder, DynamicError> {
621 match type_obj {
622 TypeObject::Complete(c) => match c {
623 CompleteTypeObject::Struct(s) => complete_struct_to_builder(s),
624 other => Err(DynamicError::unsupported(format!(
625 "complete-typeobject kind {} not yet supported",
626 other_kind_name(other)
627 ))),
628 },
629 TypeObject::Minimal(_) => Err(DynamicError::unsupported(
630 "minimal-typeobject → dynamic-type pending C4.2 TypeRegistry",
631 )),
632 }
633 }
634}
635
636fn complete_struct_to_builder(s: &CompleteStructType) -> Result<DynamicTypeBuilder, DynamicError> {
637 let mut desc = TypeDescriptor::structure(s.header.detail.type_name.clone());
638 desc.extensibility_kind = flag_bits_to_extensibility(s.struct_flags.0);
639 if (s.struct_flags.0 & StructTypeFlag::IS_NESTED) != 0 {
640 desc.is_nested = true;
641 }
642 let mut b = DynamicTypeBuilderFactory::create_type(desc)?;
643 for (idx, m) in s.member_seq.iter().enumerate() {
644 let kind = type_id_to_kind(&m.common.member_type_id)?;
645 let member_type = type_id_to_descriptor(&m.common.member_type_id, kind)?;
646 let mut md = MemberDescriptor::new(m.detail.name.clone(), m.common.member_id, member_type);
647 md.index = u32::try_from(idx).unwrap_or(u32::MAX);
648 md.is_key = (m.common.member_flags.0 & StructMemberFlag::IS_KEY) != 0;
649 md.is_optional = (m.common.member_flags.0 & StructMemberFlag::IS_OPTIONAL) != 0;
650 md.is_must_understand =
651 (m.common.member_flags.0 & StructMemberFlag::IS_MUST_UNDERSTAND) != 0;
652 md.is_shared = (m.common.member_flags.0 & StructMemberFlag::IS_EXTERNAL) != 0;
653 b.add_member(md)?;
654 }
655 Ok(b)
656}
657
658const fn other_kind_name(c: &CompleteTypeObject) -> &'static str {
659 match c {
660 CompleteTypeObject::Alias(_) => "alias",
661 CompleteTypeObject::Annotation(_) => "annotation",
662 CompleteTypeObject::Struct(_) => "struct",
663 CompleteTypeObject::Union(_) => "union",
664 CompleteTypeObject::Bitset(_) => "bitset",
665 CompleteTypeObject::Sequence(_) => "sequence",
666 CompleteTypeObject::Array(_) => "array",
667 CompleteTypeObject::Map(_) => "map",
668 CompleteTypeObject::Enumerated(_) => "enum",
669 CompleteTypeObject::Bitmask(_) => "bitmask",
670 }
671}
672
673fn type_id_to_kind(ti: &TypeIdentifier) -> Result<TypeKind, DynamicError> {
674 Ok(match ti {
675 TypeIdentifier::None => TypeKind::NoType,
676 TypeIdentifier::Primitive(p) => primitive_kind_to_type_kind(*p),
677 TypeIdentifier::String8Small { .. } | TypeIdentifier::String8Large { .. } => {
678 TypeKind::String8
679 }
680 TypeIdentifier::String16Small { .. } | TypeIdentifier::String16Large { .. } => {
681 TypeKind::String16
682 }
683 TypeIdentifier::PlainSequenceSmall { .. } | TypeIdentifier::PlainSequenceLarge { .. } => {
684 TypeKind::Sequence
685 }
686 TypeIdentifier::PlainArraySmall { .. } | TypeIdentifier::PlainArrayLarge { .. } => {
687 TypeKind::Array
688 }
689 TypeIdentifier::PlainMapSmall { .. } | TypeIdentifier::PlainMapLarge { .. } => {
690 TypeKind::Map
691 }
692 TypeIdentifier::EquivalenceHashMinimal(_) | TypeIdentifier::EquivalenceHashComplete(_) => {
693 TypeKind::Structure
696 }
697 other => {
698 return Err(DynamicError::unsupported(format!(
699 "type_id_to_kind: {other:?} not yet supported"
700 )));
701 }
702 })
703}
704
705const fn primitive_kind_to_type_kind(p: PrimitiveKind) -> TypeKind {
706 match p {
707 PrimitiveKind::Boolean => TypeKind::Boolean,
708 PrimitiveKind::Byte => TypeKind::Byte,
709 PrimitiveKind::Int8 => TypeKind::Int8,
710 PrimitiveKind::UInt8 => TypeKind::UInt8,
711 PrimitiveKind::Int16 => TypeKind::Int16,
712 PrimitiveKind::UInt16 => TypeKind::UInt16,
713 PrimitiveKind::Int32 => TypeKind::Int32,
714 PrimitiveKind::UInt32 => TypeKind::UInt32,
715 PrimitiveKind::Int64 => TypeKind::Int64,
716 PrimitiveKind::UInt64 => TypeKind::UInt64,
717 PrimitiveKind::Float32 => TypeKind::Float32,
718 PrimitiveKind::Float64 => TypeKind::Float64,
719 PrimitiveKind::Float128 => TypeKind::Float128,
720 PrimitiveKind::Char8 => TypeKind::Char8,
721 PrimitiveKind::Char16 => TypeKind::Char16,
722 }
723}
724
725fn type_id_to_descriptor(
732 ti: &TypeIdentifier,
733 kind: TypeKind,
734) -> Result<TypeDescriptor, DynamicError> {
735 if kind.is_primitive() {
736 return Ok(TypeDescriptor::primitive(
737 kind,
738 super::type_::primitive_name(kind).to_string(),
739 ));
740 }
741 Ok(match ti {
742 TypeIdentifier::String8Small { bound } => TypeDescriptor::string8(u32::from(*bound)),
743 TypeIdentifier::String8Large { bound } => TypeDescriptor::string8(*bound),
744 TypeIdentifier::String16Small { bound } => TypeDescriptor::string16(u32::from(*bound)),
745 TypeIdentifier::String16Large { bound } => TypeDescriptor::string16(*bound),
746 TypeIdentifier::None => TypeDescriptor {
747 kind: TypeKind::Structure,
748 name: String::from("<unresolved>"),
749 base_type: None,
750 discriminator_type: None,
751 bound: Vec::new(),
752 element_type: None,
753 key_element_type: None,
754 extensibility_kind: ExtensibilityKind::default(),
755 is_nested: false,
756 },
757 TypeIdentifier::EquivalenceHashMinimal(_) | TypeIdentifier::EquivalenceHashComplete(_) => {
758 TypeDescriptor {
761 kind: TypeKind::Structure,
762 name: String::from("<typeref>"),
763 base_type: None,
764 discriminator_type: None,
765 bound: Vec::new(),
766 element_type: None,
767 key_element_type: None,
768 extensibility_kind: ExtensibilityKind::default(),
769 is_nested: false,
770 }
771 }
772 TypeIdentifier::PlainSequenceSmall { bound, element, .. } => {
773 let elem_kind = type_id_to_kind(element)?;
774 TypeDescriptor::sequence(
775 "<seq>".to_string(),
776 type_id_to_descriptor(element, elem_kind)?,
777 u32::from(*bound),
778 )
779 }
780 TypeIdentifier::PlainSequenceLarge { bound, element, .. } => {
781 let elem_kind = type_id_to_kind(element)?;
782 TypeDescriptor::sequence(
783 "<seq>".to_string(),
784 type_id_to_descriptor(element, elem_kind)?,
785 *bound,
786 )
787 }
788 TypeIdentifier::PlainArraySmall {
789 array_bounds,
790 element,
791 ..
792 } => {
793 let elem_kind = type_id_to_kind(element)?;
794 TypeDescriptor::array(
795 "<arr>".to_string(),
796 type_id_to_descriptor(element, elem_kind)?,
797 array_bounds.iter().map(|b| u32::from(*b)).collect(),
798 )
799 }
800 TypeIdentifier::PlainArrayLarge {
801 array_bounds,
802 element,
803 ..
804 } => {
805 let elem_kind = type_id_to_kind(element)?;
806 TypeDescriptor::array(
807 "<arr>".to_string(),
808 type_id_to_descriptor(element, elem_kind)?,
809 array_bounds.clone(),
810 )
811 }
812 other => {
813 return Err(DynamicError::unsupported(format!(
814 "type_id_to_descriptor: {other:?} not yet supported"
815 )));
816 }
817 })
818}
819
820#[cfg(test)]
821#[allow(
822 clippy::unwrap_used,
823 clippy::expect_used,
824 clippy::panic,
825 clippy::unreachable
826)]
827mod tests {
828 use super::*;
829 use crate::dynamic::DynamicTypeBuilderFactory;
830
831 fn build_int_struct() -> DynamicType {
832 let mut b = DynamicTypeBuilderFactory::create_struct("::Sensor");
833 b.add_struct_member("id", 1, TypeDescriptor::primitive(TypeKind::Int64, "int64"))
834 .unwrap();
835 b.add_struct_member(
836 "temp",
837 2,
838 TypeDescriptor::primitive(TypeKind::Float64, "double"),
839 )
840 .unwrap();
841 b.add_struct_member("name", 3, TypeDescriptor::string8(64))
842 .unwrap();
843 b.build().unwrap()
844 }
845
846 #[test]
847 fn dynamic_struct_to_typeobject_complete() {
848 let t = build_int_struct();
849 let to = t.to_type_object().unwrap();
850 match to {
851 TypeObject::Complete(CompleteTypeObject::Struct(s)) => {
852 assert_eq!(s.header.detail.type_name, "::Sensor");
853 assert_eq!(s.member_seq.len(), 3);
854 assert_eq!(s.member_seq[0].detail.name, "id");
855 }
856 _ => panic!("to_type_object on Structure must return Complete::Struct"),
857 }
858 }
859
860 #[test]
861 fn typeobject_complete_struct_back_to_dynamic_type() {
862 let t = build_int_struct();
863 let to = t.to_type_object().unwrap();
864 let b = DynamicTypeBuilderFactory::create_type_w_type_object(&to).unwrap();
865 let t2 = b.build().unwrap();
866 assert_eq!(t2.name(), "::Sensor");
867 assert_eq!(t2.member_count(), 3);
868 assert_eq!(t2.member_by_id(1).unwrap().name(), "id");
869 assert_eq!(t2.member_by_id(2).unwrap().name(), "temp");
870 assert_eq!(t2.member_by_id(3).unwrap().name(), "name");
871 }
872
873 #[test]
874 fn roundtrip_dynamic_to_typeobject_to_dynamic_equals_logically() {
875 let t = build_int_struct();
876 let to = t.to_type_object().unwrap();
877 let b = DynamicTypeBuilderFactory::create_type_w_type_object(&to).unwrap();
878 let t2 = b.build().unwrap();
879 assert!(t.equals(&t2), "roundtrip failed: {t:?} vs {t2:?}");
881 }
882
883 #[test]
884 fn unsupported_kind_to_typeobject_yields_unsupported_error() {
885 let prim = DynamicTypeBuilderFactory::get_primitive_type(TypeKind::Int32).unwrap();
886 let err = prim.to_type_object().unwrap_err();
887 assert!(matches!(err, DynamicError::Unsupported(_)));
888 }
889
890 #[test]
891 fn dynamic_alias_to_typeobject_complete() {
892 let mut desc = TypeDescriptor::primitive(TypeKind::Int32, "int32");
894 desc.kind = TypeKind::Alias;
895 desc.name = "::SensorId".to_string();
896 desc.element_type = Some(alloc::boxed::Box::new(TypeDescriptor::primitive(
897 TypeKind::Int32,
898 "int32",
899 )));
900 let t = DynamicTypeBuilderFactory::create_type(desc)
901 .unwrap()
902 .build()
903 .unwrap();
904 let to = t.to_type_object().expect("alias bridge ok");
905 match to {
906 TypeObject::Complete(CompleteTypeObject::Alias(a)) => {
907 assert_eq!(a.header.detail.type_name, "::SensorId");
908 assert!(matches!(a.body.related_type, TypeIdentifier::Primitive(_)));
909 }
910 other => panic!("expected Alias, got {other:?}"),
911 }
912 }
913
914 #[test]
915 fn dynamic_enum_to_typeobject_complete() {
916 let mut desc = TypeDescriptor::primitive(TypeKind::Enumeration, "::Color");
917 desc.kind = TypeKind::Enumeration;
918 desc.bound = alloc::vec![32];
919 let mut b = DynamicTypeBuilderFactory::create_type(desc).unwrap();
920 for (id, name) in [(0u32, "RED"), (1u32, "GREEN"), (2u32, "BLUE")] {
921 let m = MemberDescriptor::new(
922 name,
923 id,
924 TypeDescriptor::primitive(TypeKind::Int32, "int32"),
925 );
926 b.add_member(m).unwrap();
927 }
928 let t = b.build().unwrap();
929 let to = t.to_type_object().expect("enum bridge ok");
930 match to {
931 TypeObject::Complete(CompleteTypeObject::Enumerated(e)) => {
932 assert_eq!(e.literal_seq.len(), 3);
933 assert_eq!(e.literal_seq[0].detail.name, "RED");
934 assert_eq!(e.literal_seq[2].common.value, 2);
935 }
936 other => panic!("expected Enumerated, got {other:?}"),
937 }
938 }
939
940 #[test]
941 fn dynamic_bitmask_to_typeobject_complete() {
942 let mut desc = TypeDescriptor::primitive(TypeKind::Bitmask, "::Flags");
943 desc.kind = TypeKind::Bitmask;
944 desc.bound = alloc::vec![8];
945 let mut b = DynamicTypeBuilderFactory::create_type(desc).unwrap();
946 for (pos, name) in [(0u32, "A"), (3u32, "D"), (7u32, "H")] {
947 let m = MemberDescriptor::new(
948 name,
949 pos,
950 TypeDescriptor::primitive(TypeKind::Boolean, "boolean"),
951 );
952 b.add_member(m).unwrap();
953 }
954 let t = b.build().unwrap();
955 let to = t.to_type_object().expect("bitmask bridge ok");
956 match to {
957 TypeObject::Complete(CompleteTypeObject::Bitmask(bm)) => {
958 assert_eq!(bm.bit_bound, 8);
959 assert_eq!(bm.flag_seq.len(), 3);
960 assert_eq!(bm.flag_seq[1].common.position, 3);
961 }
962 other => panic!("expected Bitmask, got {other:?}"),
963 }
964 }
965
966 #[test]
967 fn dynamic_bitset_to_typeobject_complete() {
968 let mut desc = TypeDescriptor::primitive(TypeKind::Bitset, "::Reg");
969 desc.kind = TypeKind::Bitset;
970 let mut b = DynamicTypeBuilderFactory::create_type(desc).unwrap();
971 for (pos, name, width) in [(0u32, "lo", 3u8), (3u32, "hi", 5u8)] {
972 let mut m = MemberDescriptor::new(
973 name,
974 pos,
975 TypeDescriptor::primitive(TypeKind::UInt8, "uint8"),
976 );
977 m.bit_bound = Some(width);
978 b.add_member(m).unwrap();
979 }
980 let t = b.build().unwrap();
981 let to = t.to_type_object().expect("bitset bridge ok");
982 match to {
983 TypeObject::Complete(CompleteTypeObject::Bitset(bs)) => {
984 assert_eq!(bs.field_seq.len(), 2);
985 assert_eq!(bs.field_seq[0].common.position, 0);
986 assert_eq!(bs.field_seq[0].common.bitcount, 3);
987 assert_eq!(bs.field_seq[0].detail.name, "lo");
988 assert_eq!(bs.field_seq[1].common.position, 3);
989 assert_eq!(bs.field_seq[1].common.bitcount, 5);
990 assert_eq!(
991 bs.field_seq[1].common.holder_type,
992 PrimitiveKind::UInt8.to_u8()
993 );
994 }
995 other => panic!("expected Bitset, got {other:?}"),
996 }
997 }
998
999 #[test]
1000 fn dynamic_annotation_to_typeobject_complete() {
1001 let mut desc = TypeDescriptor::primitive(TypeKind::Annotation, "::Range");
1002 desc.kind = TypeKind::Annotation;
1003 let mut b = DynamicTypeBuilderFactory::create_type(desc).unwrap();
1004 let mut m = MemberDescriptor::new(
1005 "max",
1006 1,
1007 TypeDescriptor::primitive(TypeKind::Int32, "int32"),
1008 );
1009 m.default_value = Some("100".into());
1010 b.add_member(m).unwrap();
1011 let t = b.build().unwrap();
1012 let to = t.to_type_object().expect("annotation bridge ok");
1013 match to {
1014 TypeObject::Complete(CompleteTypeObject::Annotation(a)) => {
1015 assert_eq!(a.member_seq.len(), 1);
1016 assert_eq!(a.member_seq[0].name, "max");
1017 assert_eq!(a.member_seq[0].member_id, 1);
1018 assert_eq!(a.member_seq[0].default_value, b"100".to_vec());
1019 assert!(matches!(
1020 a.member_seq[0].member_type_id,
1021 TypeIdentifier::Primitive(PrimitiveKind::Int32)
1022 ));
1023 }
1024 other => panic!("expected Annotation, got {other:?}"),
1025 }
1026 }
1027
1028 #[test]
1029 fn dynamic_sequence_to_typeobject_complete() {
1030 let desc = TypeDescriptor::sequence(
1031 "::Seq",
1032 TypeDescriptor::primitive(TypeKind::Int32, "int32"),
1033 10,
1034 );
1035 let t = DynamicTypeBuilderFactory::create_type(desc)
1036 .unwrap()
1037 .build()
1038 .unwrap();
1039 match t.to_type_object().expect("sequence bridge ok") {
1040 TypeObject::Complete(CompleteTypeObject::Sequence(s)) => {
1041 assert_eq!(s.bound, 10);
1042 assert_eq!(s.detail.type_name, "::Seq");
1043 assert!(matches!(
1044 s.element.common.type_id,
1045 TypeIdentifier::Primitive(PrimitiveKind::Int32)
1046 ));
1047 }
1048 other => panic!("expected Sequence, got {other:?}"),
1049 }
1050 }
1051
1052 #[test]
1053 fn dynamic_array_to_typeobject_complete() {
1054 let desc = TypeDescriptor::array(
1055 "::Arr",
1056 TypeDescriptor::primitive(TypeKind::Float64, "double"),
1057 alloc::vec![3, 4],
1058 );
1059 let t = DynamicTypeBuilderFactory::create_type(desc)
1060 .unwrap()
1061 .build()
1062 .unwrap();
1063 match t.to_type_object().expect("array bridge ok") {
1064 TypeObject::Complete(CompleteTypeObject::Array(a)) => {
1065 assert_eq!(a.bound_seq, alloc::vec![3, 4]);
1066 assert!(matches!(
1067 a.element.common.type_id,
1068 TypeIdentifier::Primitive(PrimitiveKind::Float64)
1069 ));
1070 }
1071 other => panic!("expected Array, got {other:?}"),
1072 }
1073 }
1074
1075 #[test]
1076 fn dynamic_map_to_typeobject_complete() {
1077 let desc = TypeDescriptor::map(
1078 "::Map",
1079 TypeDescriptor::primitive(TypeKind::Int32, "int32"),
1080 TypeDescriptor::primitive(TypeKind::Boolean, "boolean"),
1081 7,
1082 );
1083 let t = DynamicTypeBuilderFactory::create_type(desc)
1084 .unwrap()
1085 .build()
1086 .unwrap();
1087 match t.to_type_object().expect("map bridge ok") {
1088 TypeObject::Complete(CompleteTypeObject::Map(m)) => {
1089 assert_eq!(m.bound, 7);
1090 assert!(matches!(
1091 m.key.common.type_id,
1092 TypeIdentifier::Primitive(PrimitiveKind::Int32)
1093 ));
1094 assert!(matches!(
1095 m.element.common.type_id,
1096 TypeIdentifier::Primitive(PrimitiveKind::Boolean)
1097 ));
1098 }
1099 other => panic!("expected Map, got {other:?}"),
1100 }
1101 }
1102
1103 #[test]
1104 fn dynamic_union_to_typeobject_complete() {
1105 let disc = TypeDescriptor::primitive(TypeKind::Int32, "int32");
1106 let t = {
1107 let mut b = DynamicTypeBuilderFactory::create_union("::Shape", disc).unwrap();
1108 let mut m1 = MemberDescriptor::new(
1109 "circle",
1110 1,
1111 TypeDescriptor::primitive(TypeKind::Float64, "double"),
1112 );
1113 m1.label = alloc::vec![1];
1114 let mut m2 = MemberDescriptor::new(
1115 "square",
1116 2,
1117 TypeDescriptor::primitive(TypeKind::Float64, "double"),
1118 );
1119 m2.label = alloc::vec![2, 3];
1120 b.add_member(m1).unwrap();
1121 b.add_member(m2).unwrap();
1122 b.build().unwrap()
1123 };
1124 let to = t.to_type_object().expect("union bridge ok");
1125 match to {
1126 TypeObject::Complete(CompleteTypeObject::Union(u)) => {
1127 assert_eq!(u.member_seq.len(), 2);
1128 assert_eq!(u.member_seq[0].detail.name, "circle");
1129 assert_eq!(u.member_seq[1].common.label_seq, alloc::vec![2, 3]);
1130 assert!(matches!(
1131 u.discriminator.common.type_id,
1132 TypeIdentifier::Primitive(PrimitiveKind::Int32)
1133 ));
1134 }
1135 other => panic!("expected Union, got {other:?}"),
1136 }
1137 }
1138
1139 #[test]
1140 fn create_type_w_minimal_typeobject_is_unsupported() {
1141 use crate::type_object::MinimalTypeObject;
1142 use crate::type_object::minimal::{MinimalStructHeader, MinimalStructType};
1143 let m = MinimalStructType {
1144 struct_flags: StructTypeFlag::default(),
1145 header: MinimalStructHeader {
1146 base_type: TypeIdentifier::None,
1147 },
1148 member_seq: alloc::vec![],
1149 };
1150 let to = TypeObject::Minimal(MinimalTypeObject::Struct(m));
1151 let err = DynamicTypeBuilderFactory::create_type_w_type_object(&to).unwrap_err();
1152 assert!(matches!(err, DynamicError::Unsupported(_)));
1153 }
1154}