1pub mod common;
12pub mod complete;
13pub mod flags;
14pub mod kinds;
15pub mod minimal;
16
17use zerodds_cdr::{BufferReader, BufferWriter, EncodeError};
18
19use crate::error::TypeCodecError;
20use crate::type_identifier::kinds::{EK_COMPLETE, EK_MINIMAL};
21
22pub use complete::CompleteTypeObject;
23pub use minimal::MinimalTypeObject;
24
25#[allow(clippy::large_enum_variant)]
33#[derive(Debug, Clone, PartialEq, Eq)]
34#[non_exhaustive]
35pub enum TypeObject {
36 Minimal(MinimalTypeObject),
38 Complete(CompleteTypeObject),
40}
41
42impl TypeObject {
43 #[must_use]
45 pub const fn discriminator(&self) -> u8 {
46 match self {
47 Self::Minimal(_) => EK_MINIMAL,
48 Self::Complete(_) => EK_COMPLETE,
49 }
50 }
51
52 pub fn encode_into(&self, w: &mut BufferWriter) -> Result<(), EncodeError> {
57 w.write_u8(self.discriminator())?;
58 match self {
59 Self::Minimal(m) => m.encode_into(w),
60 Self::Complete(c) => c.encode_into(w),
61 }
62 }
63
64 pub fn decode_from(r: &mut BufferReader<'_>) -> Result<Self, TypeCodecError> {
69 let d = r.read_u8()?;
70 match d {
71 EK_MINIMAL => Ok(Self::Minimal(MinimalTypeObject::decode_from(r)?)),
72 EK_COMPLETE => Ok(Self::Complete(CompleteTypeObject::decode_from(r)?)),
73 other => Err(TypeCodecError::UnknownTypeKind { kind: other }),
74 }
75 }
76
77 pub fn to_bytes_le(&self) -> Result<alloc::vec::Vec<u8>, EncodeError> {
82 let mut w = BufferWriter::new(zerodds_cdr::Endianness::Little);
83 self.encode_into(&mut w)?;
84 Ok(w.into_bytes())
85 }
86
87 pub fn from_bytes_le(bytes: &[u8]) -> Result<Self, TypeCodecError> {
92 let mut r = BufferReader::new(bytes, zerodds_cdr::Endianness::Little);
93 Self::decode_from(&mut r)
94 }
95}
96
97#[cfg(test)]
102#[allow(clippy::unwrap_used, clippy::panic)]
103mod tests {
104 use super::*;
105 use crate::type_identifier::{PrimitiveKind, TypeIdentifier};
106 use crate::type_object::common::{CommonStructMember, CommonUnionMember, NameHash};
107 use crate::type_object::flags::{
108 AliasMemberFlag, AliasTypeFlag, BitmaskTypeFlag, CollectionElementFlag, CollectionTypeFlag,
109 EnumLiteralFlag, EnumTypeFlag, StructMemberFlag, StructTypeFlag, UnionDiscriminatorFlag,
110 UnionMemberFlag, UnionTypeFlag,
111 };
112 use crate::type_object::minimal::{
113 CommonAliasBody, CommonCollectionElement, CommonDiscriminatorMember,
114 CommonEnumeratedHeader, CommonEnumeratedLiteral, MinimalAliasBody, MinimalAliasType,
115 MinimalArrayType, MinimalCollectionElement, MinimalDiscriminatorMember,
116 MinimalEnumeratedHeader, MinimalEnumeratedLiteral, MinimalEnumeratedType, MinimalMapType,
117 MinimalSequenceType, MinimalStructHeader, MinimalStructMember, MinimalStructType,
118 MinimalUnionMember, MinimalUnionType,
119 };
120
121 fn roundtrip(to: TypeObject) {
122 let bytes = to.to_bytes_le().unwrap();
123 let decoded = TypeObject::from_bytes_le(&bytes).unwrap();
124 assert_eq!(to, decoded);
125 }
126
127 fn name_hash(bytes: [u8; 4]) -> NameHash {
128 NameHash(bytes)
129 }
130
131 #[test]
136 fn minimal_struct_sensor_with_two_fields() {
137 let st = MinimalStructType {
138 struct_flags: StructTypeFlag(StructTypeFlag::IS_APPENDABLE),
139 header: MinimalStructHeader {
140 base_type: TypeIdentifier::None,
141 },
142 member_seq: alloc::vec![
143 MinimalStructMember {
144 common: CommonStructMember {
145 member_id: 1,
146 member_flags: StructMemberFlag(StructMemberFlag::IS_KEY),
147 member_type_id: TypeIdentifier::Primitive(PrimitiveKind::Int64),
148 },
149 detail: name_hash([0xde, 0xad, 0xbe, 0xef]),
150 },
151 MinimalStructMember {
152 common: CommonStructMember {
153 member_id: 2,
154 member_flags: StructMemberFlag::default(),
155 member_type_id: TypeIdentifier::String8Small { bound: 128 },
156 },
157 detail: name_hash([0xfe, 0xed, 0xfa, 0xce]),
158 },
159 ],
160 };
161 roundtrip(TypeObject::Minimal(MinimalTypeObject::Struct(st)));
162 }
163
164 #[test]
165 fn minimal_struct_with_base_type() {
166 let st = MinimalStructType {
167 struct_flags: StructTypeFlag::empty(),
168 header: MinimalStructHeader {
169 base_type: TypeIdentifier::EquivalenceHashMinimal(
170 crate::type_identifier::EquivalenceHash([0x01; 14]),
171 ),
172 },
173 member_seq: alloc::vec![],
174 };
175 roundtrip(TypeObject::Minimal(MinimalTypeObject::Struct(st)));
176 }
177
178 #[test]
179 fn minimal_struct_mutable_final_flags() {
180 for flags in [
181 StructTypeFlag::IS_FINAL,
182 StructTypeFlag::IS_MUTABLE | StructTypeFlag::IS_AUTOID_HASH,
183 ] {
184 let st = MinimalStructType {
185 struct_flags: StructTypeFlag(flags),
186 header: MinimalStructHeader {
187 base_type: TypeIdentifier::None,
188 },
189 member_seq: alloc::vec![],
190 };
191 roundtrip(TypeObject::Minimal(MinimalTypeObject::Struct(st)));
192 }
193 }
194
195 #[test]
200 fn minimal_union_with_int_discriminator_two_cases() {
201 let u = MinimalUnionType {
202 union_flags: UnionTypeFlag::default(),
203 discriminator: MinimalDiscriminatorMember {
204 common: CommonDiscriminatorMember {
205 member_flags: UnionDiscriminatorFlag::default(),
206 type_id: TypeIdentifier::Primitive(PrimitiveKind::Int32),
207 },
208 },
209 member_seq: alloc::vec![
210 MinimalUnionMember {
211 common: CommonUnionMember {
212 member_id: 1,
213 member_flags: UnionMemberFlag::default(),
214 type_id: TypeIdentifier::Primitive(PrimitiveKind::Int64),
215 label_seq: alloc::vec![1, 2, 3],
216 },
217 detail: name_hash([0xaa, 0xbb, 0xcc, 0xdd]),
218 },
219 MinimalUnionMember {
220 common: CommonUnionMember {
221 member_id: 2,
222 member_flags: UnionMemberFlag(UnionMemberFlag::IS_DEFAULT),
223 type_id: TypeIdentifier::String8Small { bound: 64 },
224 label_seq: alloc::vec![],
225 },
226 detail: name_hash([0x11, 0x22, 0x33, 0x44]),
227 },
228 ],
229 };
230 roundtrip(TypeObject::Minimal(MinimalTypeObject::Union(u)));
231 }
232
233 #[test]
238 fn minimal_enum_color_3_literals() {
239 let e = MinimalEnumeratedType {
240 enum_flags: EnumTypeFlag::default(),
241 header: MinimalEnumeratedHeader {
242 common: CommonEnumeratedHeader { bit_bound: 32 },
243 },
244 literal_seq: alloc::vec![
245 MinimalEnumeratedLiteral {
246 common: CommonEnumeratedLiteral {
247 value: 0,
248 flags: EnumLiteralFlag(EnumLiteralFlag::IS_DEFAULT_LITERAL),
249 },
250 detail: name_hash([0x01, 0x02, 0x03, 0x04]),
251 },
252 MinimalEnumeratedLiteral {
253 common: CommonEnumeratedLiteral {
254 value: 1,
255 flags: EnumLiteralFlag::default(),
256 },
257 detail: name_hash([0x05, 0x06, 0x07, 0x08]),
258 },
259 MinimalEnumeratedLiteral {
260 common: CommonEnumeratedLiteral {
261 value: 2,
262 flags: EnumLiteralFlag::default(),
263 },
264 detail: name_hash([0x09, 0x0a, 0x0b, 0x0c]),
265 },
266 ],
267 };
268 roundtrip(TypeObject::Minimal(MinimalTypeObject::Enumerated(e)));
269 }
270
271 #[test]
276 fn minimal_alias_int64_typedef() {
277 let a = MinimalAliasType {
278 alias_flags: AliasTypeFlag::default(),
279 body: MinimalAliasBody {
280 common: CommonAliasBody {
281 related_flags: AliasMemberFlag::default(),
282 related_type: TypeIdentifier::Primitive(PrimitiveKind::Int64),
283 },
284 },
285 };
286 roundtrip(TypeObject::Minimal(MinimalTypeObject::Alias(a)));
287 }
288
289 #[test]
294 fn minimal_bitmask_3_flags() {
295 use crate::type_object::minimal::{CommonBitflag, MinimalBitflag, MinimalBitmaskType};
296 let b = MinimalBitmaskType {
297 bitmask_flags: BitmaskTypeFlag::default(),
298 bit_bound: 32,
299 flag_seq: alloc::vec![
300 MinimalBitflag {
301 common: CommonBitflag {
302 position: 0,
303 flags: crate::type_object::flags::BitflagFlag::default(),
304 },
305 detail: name_hash([0x10; 4]),
306 },
307 MinimalBitflag {
308 common: CommonBitflag {
309 position: 1,
310 flags: crate::type_object::flags::BitflagFlag::default(),
311 },
312 detail: name_hash([0x20; 4]),
313 },
314 MinimalBitflag {
315 common: CommonBitflag {
316 position: 2,
317 flags: crate::type_object::flags::BitflagFlag::default(),
318 },
319 detail: name_hash([0x30; 4]),
320 },
321 ],
322 };
323 roundtrip(TypeObject::Minimal(MinimalTypeObject::Bitmask(b)));
324 }
325
326 #[test]
331 fn minimal_sequence_of_floats() {
332 let s = MinimalSequenceType {
333 collection_flag: CollectionTypeFlag::default(),
334 bound: 100,
335 element: MinimalCollectionElement {
336 common: CommonCollectionElement {
337 element_flags: CollectionElementFlag::default(),
338 type_id: TypeIdentifier::Primitive(PrimitiveKind::Float64),
339 },
340 },
341 };
342 roundtrip(TypeObject::Minimal(MinimalTypeObject::Sequence(s)));
343 }
344
345 #[test]
346 fn minimal_array_3d_doubles() {
347 let a = MinimalArrayType {
348 collection_flag: CollectionTypeFlag::default(),
349 bound_seq: alloc::vec![4, 4, 4],
350 element: MinimalCollectionElement {
351 common: CommonCollectionElement {
352 element_flags: CollectionElementFlag::default(),
353 type_id: TypeIdentifier::Primitive(PrimitiveKind::Float64),
354 },
355 },
356 };
357 roundtrip(TypeObject::Minimal(MinimalTypeObject::Array(a)));
358 }
359
360 #[test]
361 fn minimal_map_string_to_int64() {
362 let m = MinimalMapType {
363 collection_flag: CollectionTypeFlag::default(),
364 bound: 1_000,
365 key: MinimalCollectionElement {
366 common: CommonCollectionElement {
367 element_flags: CollectionElementFlag::default(),
368 type_id: TypeIdentifier::String8Small { bound: 64 },
369 },
370 },
371 element: MinimalCollectionElement {
372 common: CommonCollectionElement {
373 element_flags: CollectionElementFlag::default(),
374 type_id: TypeIdentifier::Primitive(PrimitiveKind::Int64),
375 },
376 },
377 };
378 roundtrip(TypeObject::Minimal(MinimalTypeObject::Map(m)));
379 }
380
381 #[test]
386 fn minimal_annotation_with_named_parameter() {
387 use crate::type_object::flags::{AnnotationParameterFlag, AnnotationTypeFlag};
388 use crate::type_object::minimal::{
389 AnnotationParameterValue, CommonAnnotationParameter, MinimalAnnotationParameter,
390 MinimalAnnotationType,
391 };
392 let a = MinimalAnnotationType {
393 annotation_flag: AnnotationTypeFlag::default(),
394 member_seq: alloc::vec![MinimalAnnotationParameter {
395 common: CommonAnnotationParameter {
396 member_id: 1,
397 member_flags: AnnotationParameterFlag::default(),
398 member_type_id: TypeIdentifier::Primitive(PrimitiveKind::Int32),
399 },
400 name: alloc::string::String::from("max"),
401 default_value: AnnotationParameterValue {
402 raw: alloc::vec![0, 0, 0, 10],
403 },
404 }],
405 };
406 roundtrip(TypeObject::Minimal(MinimalTypeObject::Annotation(a)));
407 }
408
409 #[test]
414 fn minimal_bitset_roundtrips() {
415 use crate::type_object::flags::{BitfieldFlag, BitsetTypeFlag};
416 use crate::type_object::minimal::{CommonBitfield, MinimalBitfield, MinimalBitsetType};
417 let b = MinimalBitsetType {
418 bitset_flags: BitsetTypeFlag::default(),
419 field_seq: alloc::vec![MinimalBitfield {
420 common: CommonBitfield {
421 position: 0,
422 flags: BitfieldFlag::default(),
423 bitcount: 3,
424 holder_type: 0x07, },
426 name_hash: name_hash([0xab; 4]),
427 }],
428 };
429 roundtrip(TypeObject::Minimal(MinimalTypeObject::Bitset(b)));
430 }
431
432 #[test]
437 fn complete_struct_sensor_with_names_and_annotations() {
438 use crate::type_object::common::{
439 AppliedAnnotation, AppliedAnnotationParameter, AppliedBuiltinMemberAnnotations,
440 AppliedBuiltinTypeAnnotations, AppliedVerbatimAnnotation, CompleteMemberDetail,
441 CompleteTypeDetail, OptionalAppliedAnnotationSeq, VerbatimPlacement,
442 };
443 use crate::type_object::complete::{
444 CompleteStructHeader, CompleteStructMember, CompleteStructType,
445 };
446 let st = CompleteStructType {
447 struct_flags: StructTypeFlag(StructTypeFlag::IS_MUTABLE),
448 header: CompleteStructHeader {
449 base_type: TypeIdentifier::None,
450 detail: CompleteTypeDetail {
451 ann_builtin: AppliedBuiltinTypeAnnotations {
452 verbatim: Some(AppliedVerbatimAnnotation {
453 placement: VerbatimPlacement::Before,
454 language: alloc::string::String::from("c++"),
455 text: alloc::string::String::from("// hand-written"),
456 }),
457 },
458 ann_custom: OptionalAppliedAnnotationSeq(Some(alloc::vec![
459 AppliedAnnotation {
460 annotation_typeid: TypeIdentifier::EquivalenceHashComplete(
461 crate::type_identifier::EquivalenceHash([0xA0; 14]),
462 ),
463 param_seq: alloc::vec![AppliedAnnotationParameter {
464 paramname_hash: name_hash([0x01; 4]),
465 value: alloc::vec![0, 0, 0, 42],
466 }],
467 },
468 ])),
469 type_name: alloc::string::String::from("::sensors::Chatter"),
470 },
471 },
472 member_seq: alloc::vec![CompleteStructMember {
473 common: CommonStructMember {
474 member_id: 1,
475 member_flags: StructMemberFlag(StructMemberFlag::IS_KEY),
476 member_type_id: TypeIdentifier::Primitive(PrimitiveKind::Int64),
477 },
478 detail: CompleteMemberDetail {
479 name: alloc::string::String::from("sensor_id"),
480 ann_builtin: AppliedBuiltinMemberAnnotations {
481 unit: Some(alloc::string::String::from("celsius")),
482 min: Some(alloc::vec![0, 0, 0, 0]),
483 max: Some(alloc::vec![0xff, 0xff, 0xff, 0xff]),
484 hash_id: None,
485 default_value: None,
486 },
487 ann_custom: OptionalAppliedAnnotationSeq::default(),
488 },
489 }],
490 };
491 roundtrip(TypeObject::Complete(CompleteTypeObject::Struct(st)));
492 }
493
494 #[test]
495 fn complete_union_roundtrips() {
496 use crate::type_object::common::{
497 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
498 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
499 };
500 use crate::type_object::complete::{
501 CompleteDiscriminatorMember, CompleteUnionHeader, CompleteUnionMember,
502 CompleteUnionType,
503 };
504 let u = CompleteUnionType {
505 union_flags: UnionTypeFlag::default(),
506 header: CompleteUnionHeader {
507 detail: CompleteTypeDetail {
508 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
509 ann_custom: OptionalAppliedAnnotationSeq::default(),
510 type_name: alloc::string::String::from("::MyUnion"),
511 },
512 },
513 discriminator: CompleteDiscriminatorMember {
514 common: CommonDiscriminatorMember {
515 member_flags: UnionDiscriminatorFlag::default(),
516 type_id: TypeIdentifier::Primitive(PrimitiveKind::Int32),
517 },
518 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
519 ann_custom: OptionalAppliedAnnotationSeq::default(),
520 },
521 member_seq: alloc::vec![CompleteUnionMember {
522 common: CommonUnionMember {
523 member_id: 1,
524 member_flags: UnionMemberFlag::default(),
525 type_id: TypeIdentifier::Primitive(PrimitiveKind::Int64),
526 label_seq: alloc::vec![42],
527 },
528 detail: CompleteMemberDetail {
529 name: alloc::string::String::from("value"),
530 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
531 ann_custom: OptionalAppliedAnnotationSeq::default(),
532 },
533 }],
534 };
535 roundtrip(TypeObject::Complete(CompleteTypeObject::Union(u)));
536 }
537
538 #[test]
539 fn complete_enum_with_literal_names() {
540 use crate::type_object::common::{
541 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
542 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
543 };
544 use crate::type_object::complete::{
545 CompleteEnumeratedHeader, CompleteEnumeratedLiteral, CompleteEnumeratedType,
546 };
547 let e = CompleteEnumeratedType {
548 enum_flags: EnumTypeFlag::default(),
549 header: CompleteEnumeratedHeader {
550 common: CommonEnumeratedHeader { bit_bound: 32 },
551 detail: CompleteTypeDetail {
552 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
553 ann_custom: OptionalAppliedAnnotationSeq::default(),
554 type_name: alloc::string::String::from("::Color"),
555 },
556 },
557 literal_seq: alloc::vec![
558 CompleteEnumeratedLiteral {
559 common: CommonEnumeratedLiteral {
560 value: 0,
561 flags: EnumLiteralFlag(EnumLiteralFlag::IS_DEFAULT_LITERAL),
562 },
563 detail: CompleteMemberDetail {
564 name: alloc::string::String::from("RED"),
565 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
566 ann_custom: OptionalAppliedAnnotationSeq::default(),
567 },
568 },
569 CompleteEnumeratedLiteral {
570 common: CommonEnumeratedLiteral {
571 value: 1,
572 flags: EnumLiteralFlag::default(),
573 },
574 detail: CompleteMemberDetail {
575 name: alloc::string::String::from("GREEN"),
576 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
577 ann_custom: OptionalAppliedAnnotationSeq::default(),
578 },
579 },
580 ],
581 };
582 roundtrip(TypeObject::Complete(CompleteTypeObject::Enumerated(e)));
583 }
584
585 #[test]
586 fn complete_alias_typedef() {
587 use crate::type_object::common::{
588 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteTypeDetail,
589 OptionalAppliedAnnotationSeq,
590 };
591 use crate::type_object::complete::{
592 CompleteAliasBody, CompleteAliasHeader, CompleteAliasType,
593 };
594 let a = CompleteAliasType {
595 alias_flags: AliasTypeFlag::default(),
596 header: CompleteAliasHeader {
597 detail: CompleteTypeDetail {
598 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
599 ann_custom: OptionalAppliedAnnotationSeq::default(),
600 type_name: alloc::string::String::from("::Count"),
601 },
602 },
603 body: CompleteAliasBody {
604 related_flags: AliasMemberFlag::default(),
605 related_type: TypeIdentifier::Primitive(PrimitiveKind::UInt64),
606 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
607 ann_custom: OptionalAppliedAnnotationSeq::default(),
608 },
609 };
610 roundtrip(TypeObject::Complete(CompleteTypeObject::Alias(a)));
611 }
612
613 #[test]
614 fn complete_array_3d_roundtrips() {
615 use crate::type_object::common::{
616 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteTypeDetail,
617 OptionalAppliedAnnotationSeq,
618 };
619 use crate::type_object::complete::{CompleteArrayType, CompleteCollectionElement};
620 let a = CompleteArrayType {
621 collection_flag: CollectionTypeFlag::default(),
622 bound_seq: alloc::vec![3, 4, 5],
623 detail: CompleteTypeDetail {
624 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
625 ann_custom: OptionalAppliedAnnotationSeq::default(),
626 type_name: alloc::string::String::from("::Cube"),
627 },
628 element: CompleteCollectionElement {
629 common: CommonCollectionElement {
630 element_flags: CollectionElementFlag::default(),
631 type_id: TypeIdentifier::Primitive(PrimitiveKind::Int32),
632 },
633 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
634 ann_custom: OptionalAppliedAnnotationSeq::default(),
635 },
636 };
637 roundtrip(TypeObject::Complete(CompleteTypeObject::Array(a)));
638 }
639
640 #[test]
641 fn complete_map_roundtrips() {
642 use crate::type_object::common::{
643 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteTypeDetail,
644 OptionalAppliedAnnotationSeq,
645 };
646 use crate::type_object::complete::{CompleteCollectionElement, CompleteMapType};
647 let m = CompleteMapType {
648 collection_flag: CollectionTypeFlag::default(),
649 bound: 200,
650 detail: CompleteTypeDetail {
651 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
652 ann_custom: OptionalAppliedAnnotationSeq::default(),
653 type_name: alloc::string::String::from("::StrIntMap"),
654 },
655 key: CompleteCollectionElement {
656 common: CommonCollectionElement {
657 element_flags: CollectionElementFlag::default(),
658 type_id: TypeIdentifier::String8Small { bound: 32 },
659 },
660 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
661 ann_custom: OptionalAppliedAnnotationSeq::default(),
662 },
663 element: CompleteCollectionElement {
664 common: CommonCollectionElement {
665 element_flags: CollectionElementFlag::default(),
666 type_id: TypeIdentifier::Primitive(PrimitiveKind::Int64),
667 },
668 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
669 ann_custom: OptionalAppliedAnnotationSeq::default(),
670 },
671 };
672 roundtrip(TypeObject::Complete(CompleteTypeObject::Map(m)));
673 }
674
675 #[test]
676 fn complete_bitmask_roundtrips() {
677 use crate::type_object::common::{
678 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
679 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
680 };
681 use crate::type_object::complete::{CompleteBitflag, CompleteBitmaskType};
682 use crate::type_object::flags::BitflagFlag;
683 let b = CompleteBitmaskType {
684 bitmask_flags: BitmaskTypeFlag::default(),
685 bit_bound: 32,
686 detail: CompleteTypeDetail {
687 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
688 ann_custom: OptionalAppliedAnnotationSeq::default(),
689 type_name: alloc::string::String::from("::Perms"),
690 },
691 flag_seq: alloc::vec![
692 CompleteBitflag {
693 common: crate::type_object::minimal::CommonBitflag {
694 position: 0,
695 flags: BitflagFlag::default(),
696 },
697 detail: CompleteMemberDetail {
698 name: alloc::string::String::from("READ"),
699 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
700 ann_custom: OptionalAppliedAnnotationSeq::default(),
701 },
702 },
703 CompleteBitflag {
704 common: crate::type_object::minimal::CommonBitflag {
705 position: 1,
706 flags: BitflagFlag::default(),
707 },
708 detail: CompleteMemberDetail {
709 name: alloc::string::String::from("WRITE"),
710 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
711 ann_custom: OptionalAppliedAnnotationSeq::default(),
712 },
713 },
714 ],
715 };
716 roundtrip(TypeObject::Complete(CompleteTypeObject::Bitmask(b)));
717 }
718
719 #[test]
720 fn complete_bitset_roundtrips() {
721 use crate::type_object::common::{
722 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
723 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
724 };
725 use crate::type_object::complete::{CompleteBitfield, CompleteBitsetType};
726 use crate::type_object::flags::{BitfieldFlag, BitsetTypeFlag};
727 let b = CompleteBitsetType {
728 bitset_flags: BitsetTypeFlag::default(),
729 detail: CompleteTypeDetail {
730 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
731 ann_custom: OptionalAppliedAnnotationSeq::default(),
732 type_name: alloc::string::String::from("::Packed"),
733 },
734 field_seq: alloc::vec![CompleteBitfield {
735 common: crate::type_object::minimal::CommonBitfield {
736 position: 0,
737 flags: BitfieldFlag::default(),
738 bitcount: 3,
739 holder_type: 0x07,
740 },
741 detail: CompleteMemberDetail {
742 name: alloc::string::String::from("a"),
743 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
744 ann_custom: OptionalAppliedAnnotationSeq::default(),
745 },
746 }],
747 };
748 roundtrip(TypeObject::Complete(CompleteTypeObject::Bitset(b)));
749 }
750
751 #[test]
752 fn complete_annotation_roundtrips() {
753 use crate::type_object::common::{
754 AppliedBuiltinTypeAnnotations, CompleteTypeDetail, OptionalAppliedAnnotationSeq,
755 };
756 use crate::type_object::complete::{CompleteAnnotationParameter, CompleteAnnotationType};
757 use crate::type_object::flags::{AnnotationParameterFlag, AnnotationTypeFlag};
758 let a = CompleteAnnotationType {
759 annotation_flag: AnnotationTypeFlag::default(),
760 detail: CompleteTypeDetail {
761 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
762 ann_custom: OptionalAppliedAnnotationSeq::default(),
763 type_name: alloc::string::String::from("::my_ann"),
764 },
765 member_seq: alloc::vec![CompleteAnnotationParameter {
766 member_id: 1,
767 member_flags: AnnotationParameterFlag::default(),
768 member_type_id: TypeIdentifier::Primitive(PrimitiveKind::Int32),
769 name: alloc::string::String::from("max"),
770 default_value: alloc::vec![0, 0, 0, 99],
771 }],
772 };
773 roundtrip(TypeObject::Complete(CompleteTypeObject::Annotation(a)));
774 }
775
776 #[test]
777 fn complete_verbatim_placement_variants_roundtrip() {
778 use crate::type_object::common::{
779 AppliedBuiltinTypeAnnotations, AppliedVerbatimAnnotation, CompleteTypeDetail,
780 OptionalAppliedAnnotationSeq, VerbatimPlacement,
781 };
782 use crate::type_object::complete::{CompleteStructHeader, CompleteStructType};
783 for placement in [
784 VerbatimPlacement::Before,
785 VerbatimPlacement::After,
786 VerbatimPlacement::BeginFile,
787 VerbatimPlacement::EndFile,
788 VerbatimPlacement::Other(alloc::string::String::from("CUSTOM")),
789 ] {
790 let st = CompleteStructType {
791 struct_flags: StructTypeFlag::empty(),
792 header: CompleteStructHeader {
793 base_type: TypeIdentifier::None,
794 detail: CompleteTypeDetail {
795 ann_builtin: AppliedBuiltinTypeAnnotations {
796 verbatim: Some(AppliedVerbatimAnnotation {
797 placement: placement.clone(),
798 language: alloc::string::String::from("rust"),
799 text: alloc::string::String::from("// hand written"),
800 }),
801 },
802 ann_custom: OptionalAppliedAnnotationSeq::default(),
803 type_name: alloc::string::String::from("::X"),
804 },
805 },
806 member_seq: alloc::vec![],
807 };
808 roundtrip(TypeObject::Complete(CompleteTypeObject::Struct(st)));
809 }
810 }
811
812 #[test]
813 fn complete_sequence_of_floats() {
814 use crate::type_object::common::{
815 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteTypeDetail,
816 OptionalAppliedAnnotationSeq,
817 };
818 use crate::type_object::complete::{CompleteCollectionElement, CompleteSequenceType};
819 let s = CompleteSequenceType {
820 collection_flag: CollectionTypeFlag::default(),
821 bound: 128,
822 detail: CompleteTypeDetail {
823 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
824 ann_custom: OptionalAppliedAnnotationSeq::default(),
825 type_name: alloc::string::String::from("::Floats"),
826 },
827 element: CompleteCollectionElement {
828 common: CommonCollectionElement {
829 element_flags: CollectionElementFlag::default(),
830 type_id: TypeIdentifier::Primitive(PrimitiveKind::Float64),
831 },
832 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
833 ann_custom: OptionalAppliedAnnotationSeq::default(),
834 },
835 };
836 roundtrip(TypeObject::Complete(CompleteTypeObject::Sequence(s)));
837 }
838
839 #[test]
844 fn unknown_equivalence_kind_fails_gracefully() {
845 let bytes = [0xAB_u8];
846 let err = TypeObject::from_bytes_le(&bytes).unwrap_err();
847 assert!(matches!(
848 err,
849 TypeCodecError::UnknownTypeKind { kind: 0xAB }
850 ));
851 }
852}