1use alloc::string::String;
31use alloc::vec::Vec;
32
33use crate::type_identifier::TypeIdentifier;
34use crate::type_object::common::{
35 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CommonStructMember,
36 CompleteMemberDetail, CompleteTypeDetail, NameHash, OptionalAppliedAnnotationSeq,
37};
38use crate::type_object::complete::{
39 CompleteAliasBody, CompleteAliasHeader, CompleteAliasType, CompleteEnumeratedHeader,
40 CompleteEnumeratedLiteral, CompleteEnumeratedType, CompleteStructHeader, CompleteStructMember,
41 CompleteStructType,
42};
43use crate::type_object::flags::{
44 AliasMemberFlag, AliasTypeFlag, EnumLiteralFlag, EnumTypeFlag, StructMemberFlag, StructTypeFlag,
45};
46use crate::type_object::minimal::CommonAliasBody;
47use crate::type_object::minimal::{
48 CommonEnumeratedHeader, CommonEnumeratedLiteral, MinimalAliasBody, MinimalAliasType,
49 MinimalEnumeratedHeader, MinimalEnumeratedLiteral, MinimalEnumeratedType, MinimalStructHeader,
50 MinimalStructMember, MinimalStructType,
51};
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum Extensibility {
57 Final,
59 Appendable,
61 Mutable,
63}
64
65impl Default for Extensibility {
66 fn default() -> Self {
67 Self::Appendable
68 }
69}
70
71impl Extensibility {
72 const fn to_flag_bits(self) -> u16 {
73 match self {
74 Self::Final => StructTypeFlag::IS_FINAL,
75 Self::Appendable => StructTypeFlag::IS_APPENDABLE,
76 Self::Mutable => StructTypeFlag::IS_MUTABLE,
77 }
78 }
79}
80
81pub struct TypeObjectBuilder;
83
84impl TypeObjectBuilder {
85 #[must_use]
88 pub fn struct_type(name: impl Into<String>) -> StructBuilder {
89 StructBuilder {
90 name: name.into(),
91 extensibility: Extensibility::default(),
92 nested: false,
93 autoid_hash: false,
94 base_type: TypeIdentifier::None,
95 members: Vec::new(),
96 }
97 }
98
99 #[must_use]
101 pub fn enum_type(name: impl Into<String>) -> EnumBuilder {
102 EnumBuilder {
103 name: name.into(),
104 bit_bound: 32,
105 literals: Vec::new(),
106 }
107 }
108
109 #[must_use]
111 pub fn alias(name: impl Into<String>, target: TypeIdentifier) -> AliasBuilder {
112 AliasBuilder {
113 name: name.into(),
114 related_type: target,
115 }
116 }
117}
118
119pub struct StructBuilder {
125 name: String,
126 extensibility: Extensibility,
127 nested: bool,
128 autoid_hash: bool,
129 base_type: TypeIdentifier,
130 members: Vec<StructMemberSpec>,
131}
132
133pub struct StructMemberSpec {
135 name: String,
136 type_id: TypeIdentifier,
137 explicit_id: Option<u32>,
138 flags: u16,
139 unit: Option<String>,
140 min: Option<Vec<u8>>,
141 max: Option<Vec<u8>>,
142 hash_id: Option<String>,
143 default_value: Option<String>,
144}
145
146pub struct StructMemberBuilder<'a> {
148 spec: &'a mut StructMemberSpec,
149}
150
151impl StructMemberBuilder<'_> {
152 #[must_use]
154 pub fn key(self) -> Self {
155 self.spec.flags |= StructMemberFlag::IS_KEY;
156 self
157 }
158
159 #[must_use]
161 pub fn optional(self) -> Self {
162 self.spec.flags |= StructMemberFlag::IS_OPTIONAL;
163 self
164 }
165
166 #[must_use]
168 pub fn must_understand(self) -> Self {
169 self.spec.flags |= StructMemberFlag::IS_MUST_UNDERSTAND;
170 self
171 }
172
173 #[must_use]
175 pub fn external(self) -> Self {
176 self.spec.flags |= StructMemberFlag::IS_EXTERNAL;
177 self
178 }
179
180 #[must_use]
182 pub fn id(self, id: u32) -> Self {
183 self.spec.explicit_id = Some(id);
184 self
185 }
186
187 #[must_use]
189 pub fn unit(self, unit: impl Into<String>) -> Self {
190 self.spec.unit = Some(unit.into());
191 self
192 }
193
194 #[must_use]
196 pub fn min_bytes(self, min: Vec<u8>) -> Self {
197 self.spec.min = Some(min);
198 self
199 }
200
201 #[must_use]
203 pub fn max_bytes(self, max: Vec<u8>) -> Self {
204 self.spec.max = Some(max);
205 self
206 }
207
208 #[must_use]
210 pub fn hash_id(self, name: impl Into<String>) -> Self {
211 self.spec.hash_id = Some(name.into());
212 self
213 }
214
215 #[must_use]
219 pub fn set_member_default(self, value: impl Into<String>) -> Self {
220 self.spec.default_value = Some(value.into());
221 self
222 }
223}
224
225impl StructBuilder {
226 #[must_use]
228 pub fn extensibility(mut self, ext: Extensibility) -> Self {
229 self.extensibility = ext;
230 self
231 }
232
233 #[must_use]
235 pub fn nested(mut self) -> Self {
236 self.nested = true;
237 self
238 }
239
240 #[must_use]
242 pub fn autoid_hash(mut self) -> Self {
243 self.autoid_hash = true;
244 self
245 }
246
247 #[must_use]
249 pub fn base(mut self, base: TypeIdentifier) -> Self {
250 self.base_type = base;
251 self
252 }
253
254 #[must_use]
259 pub fn member<F>(mut self, name: impl Into<String>, ty: TypeIdentifier, f: F) -> Self
260 where
261 F: FnOnce(StructMemberBuilder<'_>) -> StructMemberBuilder<'_>,
262 {
263 let mut spec = StructMemberSpec {
264 name: name.into(),
265 type_id: ty,
266 explicit_id: None,
267 flags: 0,
268 unit: None,
269 min: None,
270 max: None,
271 hash_id: None,
272 default_value: None,
273 };
274 let _ = f(StructMemberBuilder { spec: &mut spec });
275 self.members.push(spec);
276 self
277 }
278
279 fn struct_flags(&self) -> StructTypeFlag {
280 let mut bits = self.extensibility.to_flag_bits();
281 if self.nested {
282 bits |= StructTypeFlag::IS_NESTED;
283 }
284 if self.autoid_hash {
285 bits |= StructTypeFlag::IS_AUTOID_HASH;
286 }
287 StructTypeFlag(bits)
288 }
289
290 fn resolve_member_ids(&self) -> Vec<u32> {
295 let mut ids = Vec::with_capacity(self.members.len());
296 let mut next_seq: u32 = 1;
297 for spec in &self.members {
298 let id = if let Some(explicit) = spec.explicit_id {
299 explicit
300 } else if self.autoid_hash {
301 let nh = NameHash::from_name(&spec.name);
306 (u32::from_le_bytes(nh.0) >> 4) & 0x00FF_FFFF
307 } else {
308 let v = next_seq;
309 next_seq += 1;
310 v
311 };
312 ids.push(id);
313 }
314 ids
315 }
316
317 fn member_common(spec: &StructMemberSpec, id: u32) -> CommonStructMember {
318 CommonStructMember {
319 member_id: id,
320 member_flags: StructMemberFlag(spec.flags),
321 member_type_id: spec.type_id.clone(),
322 }
323 }
324
325 fn member_detail(spec: &StructMemberSpec) -> CompleteMemberDetail {
326 CompleteMemberDetail {
327 name: spec.name.clone(),
328 ann_builtin: AppliedBuiltinMemberAnnotations {
329 unit: spec.unit.clone(),
330 min: spec.min.clone(),
331 max: spec.max.clone(),
332 hash_id: spec.hash_id.clone(),
333 default_value: spec.default_value.clone(),
334 },
335 ann_custom: OptionalAppliedAnnotationSeq::default(),
336 }
337 }
338
339 #[must_use]
341 pub fn build_minimal(&self) -> MinimalStructType {
342 let ids = self.resolve_member_ids();
343 let member_seq = self
344 .members
345 .iter()
346 .zip(ids.iter())
347 .map(|(spec, id)| MinimalStructMember {
348 common: Self::member_common(spec, *id),
349 detail: NameHash::from_name(&spec.name),
350 })
351 .collect();
352 MinimalStructType {
353 struct_flags: self.struct_flags(),
354 header: MinimalStructHeader {
355 base_type: self.base_type.clone(),
356 },
357 member_seq,
358 }
359 }
360
361 #[must_use]
363 pub fn build_complete(&self) -> CompleteStructType {
364 let ids = self.resolve_member_ids();
365 let member_seq = self
366 .members
367 .iter()
368 .zip(ids.iter())
369 .map(|(spec, id)| CompleteStructMember {
370 common: Self::member_common(spec, *id),
371 detail: Self::member_detail(spec),
372 })
373 .collect();
374 CompleteStructType {
375 struct_flags: self.struct_flags(),
376 header: CompleteStructHeader {
377 base_type: self.base_type.clone(),
378 detail: CompleteTypeDetail {
379 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
380 ann_custom: OptionalAppliedAnnotationSeq::default(),
381 type_name: self.name.clone(),
382 },
383 },
384 member_seq,
385 }
386 }
387}
388
389pub struct EnumBuilder {
395 name: String,
396 bit_bound: u16,
397 literals: Vec<EnumLiteralSpec>,
398}
399
400struct EnumLiteralSpec {
401 name: String,
402 value: i32,
403 is_default: bool,
404}
405
406impl EnumBuilder {
407 #[must_use]
409 pub fn bit_bound(mut self, bits: u16) -> Self {
410 self.bit_bound = bits;
411 self
412 }
413
414 #[must_use]
416 pub fn literal(mut self, name: impl Into<String>, value: i32) -> Self {
417 self.literals.push(EnumLiteralSpec {
418 name: name.into(),
419 value,
420 is_default: false,
421 });
422 self
423 }
424
425 #[must_use]
427 pub fn default_literal(mut self, name: impl Into<String>, value: i32) -> Self {
428 self.literals.push(EnumLiteralSpec {
429 name: name.into(),
430 value,
431 is_default: true,
432 });
433 self
434 }
435
436 #[must_use]
438 pub fn build_minimal(&self) -> MinimalEnumeratedType {
439 MinimalEnumeratedType {
440 enum_flags: EnumTypeFlag::default(),
441 header: MinimalEnumeratedHeader {
442 common: CommonEnumeratedHeader {
443 bit_bound: self.bit_bound,
444 },
445 },
446 literal_seq: self
447 .literals
448 .iter()
449 .map(|l| MinimalEnumeratedLiteral {
450 common: CommonEnumeratedLiteral {
451 value: l.value,
452 flags: EnumLiteralFlag(if l.is_default {
453 EnumLiteralFlag::IS_DEFAULT_LITERAL
454 } else {
455 0
456 }),
457 },
458 detail: NameHash::from_name(&l.name),
459 })
460 .collect(),
461 }
462 }
463
464 #[must_use]
466 pub fn build_complete(&self) -> CompleteEnumeratedType {
467 CompleteEnumeratedType {
468 enum_flags: EnumTypeFlag::default(),
469 header: CompleteEnumeratedHeader {
470 common: CommonEnumeratedHeader {
471 bit_bound: self.bit_bound,
472 },
473 detail: CompleteTypeDetail {
474 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
475 ann_custom: OptionalAppliedAnnotationSeq::default(),
476 type_name: self.name.clone(),
477 },
478 },
479 literal_seq: self
480 .literals
481 .iter()
482 .map(|l| CompleteEnumeratedLiteral {
483 common: CommonEnumeratedLiteral {
484 value: l.value,
485 flags: EnumLiteralFlag(if l.is_default {
486 EnumLiteralFlag::IS_DEFAULT_LITERAL
487 } else {
488 0
489 }),
490 },
491 detail: CompleteMemberDetail {
492 name: l.name.clone(),
493 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
494 ann_custom: OptionalAppliedAnnotationSeq::default(),
495 },
496 })
497 .collect(),
498 }
499 }
500}
501
502pub struct AliasBuilder {
508 name: String,
509 related_type: TypeIdentifier,
510}
511
512impl AliasBuilder {
513 #[must_use]
515 pub fn build_minimal(&self) -> MinimalAliasType {
516 MinimalAliasType {
517 alias_flags: AliasTypeFlag::default(),
518 body: MinimalAliasBody {
519 common: CommonAliasBody {
520 related_flags: AliasMemberFlag::default(),
521 related_type: self.related_type.clone(),
522 },
523 },
524 }
525 }
526
527 #[must_use]
529 pub fn build_complete(&self) -> CompleteAliasType {
530 CompleteAliasType {
531 alias_flags: AliasTypeFlag::default(),
532 header: CompleteAliasHeader {
533 detail: CompleteTypeDetail {
534 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
535 ann_custom: OptionalAppliedAnnotationSeq::default(),
536 type_name: self.name.clone(),
537 },
538 },
539 body: CompleteAliasBody {
540 related_flags: AliasMemberFlag::default(),
541 related_type: self.related_type.clone(),
542 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
543 ann_custom: OptionalAppliedAnnotationSeq::default(),
544 },
545 }
546 }
547}
548
549pub struct UnionBuilder {
555 name: String,
556 extensibility: Extensibility,
557 discriminator_type: TypeIdentifier,
558 cases: Vec<UnionCaseSpec>,
559}
560
561struct UnionCaseSpec {
562 name: String,
563 member_id: Option<u32>,
564 type_id: TypeIdentifier,
565 labels: Vec<i32>,
566 is_default: bool,
567}
568
569impl UnionBuilder {
570 #[must_use]
572 pub fn extensibility(mut self, ext: Extensibility) -> Self {
573 self.extensibility = ext;
574 self
575 }
576
577 #[must_use]
579 pub fn case(mut self, name: impl Into<String>, ty: TypeIdentifier, labels: Vec<i32>) -> Self {
580 self.cases.push(UnionCaseSpec {
581 name: name.into(),
582 member_id: None,
583 type_id: ty,
584 labels,
585 is_default: false,
586 });
587 self
588 }
589
590 #[must_use]
592 pub fn default_case(mut self, name: impl Into<String>, ty: TypeIdentifier) -> Self {
593 self.cases.push(UnionCaseSpec {
594 name: name.into(),
595 member_id: None,
596 type_id: ty,
597 labels: Vec::new(),
598 is_default: true,
599 });
600 self
601 }
602
603 fn union_flags(&self) -> crate::type_object::flags::UnionTypeFlag {
604 use crate::type_object::flags::UnionTypeFlag;
605 UnionTypeFlag(match self.extensibility {
608 Extensibility::Final => StructTypeFlag::IS_FINAL,
609 Extensibility::Appendable => StructTypeFlag::IS_APPENDABLE,
610 Extensibility::Mutable => StructTypeFlag::IS_MUTABLE,
611 })
612 }
613
614 fn resolve_case_ids(&self) -> Vec<u32> {
615 let mut ids = Vec::with_capacity(self.cases.len());
616 let mut next: u32 = 1;
617 for c in &self.cases {
618 ids.push(c.member_id.unwrap_or_else(|| {
619 let v = next;
620 next += 1;
621 v
622 }));
623 }
624 ids
625 }
626
627 #[must_use]
629 pub fn build_minimal(&self) -> crate::type_object::minimal::MinimalUnionType {
630 use crate::type_object::common::CommonUnionMember;
631 use crate::type_object::flags::{UnionDiscriminatorFlag, UnionMemberFlag};
632 use crate::type_object::minimal::{
633 CommonDiscriminatorMember, MinimalDiscriminatorMember, MinimalUnionMember,
634 MinimalUnionType,
635 };
636 let ids = self.resolve_case_ids();
637 let member_seq = self
638 .cases
639 .iter()
640 .zip(ids.iter())
641 .map(|(c, id)| MinimalUnionMember {
642 common: CommonUnionMember {
643 member_id: *id,
644 member_flags: UnionMemberFlag(if c.is_default {
645 UnionMemberFlag::IS_DEFAULT
646 } else {
647 0
648 }),
649 type_id: c.type_id.clone(),
650 label_seq: c.labels.clone(),
651 },
652 detail: NameHash::from_name(&c.name),
653 })
654 .collect();
655 MinimalUnionType {
656 union_flags: self.union_flags(),
657 discriminator: MinimalDiscriminatorMember {
658 common: CommonDiscriminatorMember {
659 member_flags: UnionDiscriminatorFlag::default(),
660 type_id: self.discriminator_type.clone(),
661 },
662 },
663 member_seq,
664 }
665 }
666
667 #[must_use]
669 pub fn build_complete(&self) -> crate::type_object::complete::CompleteUnionType {
670 use crate::type_object::common::CommonUnionMember;
671 use crate::type_object::complete::{
672 CompleteDiscriminatorMember, CompleteUnionHeader, CompleteUnionMember,
673 CompleteUnionType,
674 };
675 use crate::type_object::flags::{UnionDiscriminatorFlag, UnionMemberFlag};
676 use crate::type_object::minimal::CommonDiscriminatorMember;
677 let ids = self.resolve_case_ids();
678 let member_seq = self
679 .cases
680 .iter()
681 .zip(ids.iter())
682 .map(|(c, id)| CompleteUnionMember {
683 common: CommonUnionMember {
684 member_id: *id,
685 member_flags: UnionMemberFlag(if c.is_default {
686 UnionMemberFlag::IS_DEFAULT
687 } else {
688 0
689 }),
690 type_id: c.type_id.clone(),
691 label_seq: c.labels.clone(),
692 },
693 detail: CompleteMemberDetail {
694 name: c.name.clone(),
695 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
696 ann_custom: OptionalAppliedAnnotationSeq::default(),
697 },
698 })
699 .collect();
700 CompleteUnionType {
701 union_flags: self.union_flags(),
702 header: CompleteUnionHeader {
703 detail: CompleteTypeDetail {
704 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
705 ann_custom: OptionalAppliedAnnotationSeq::default(),
706 type_name: self.name.clone(),
707 },
708 },
709 discriminator: CompleteDiscriminatorMember {
710 common: CommonDiscriminatorMember {
711 member_flags: UnionDiscriminatorFlag::default(),
712 type_id: self.discriminator_type.clone(),
713 },
714 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
715 ann_custom: OptionalAppliedAnnotationSeq::default(),
716 },
717 member_seq,
718 }
719 }
720}
721
722pub struct SequenceBuilder {
728 element: TypeIdentifier,
729 bound: u32,
730}
731
732impl SequenceBuilder {
733 #[must_use]
735 pub fn build_minimal(&self) -> crate::type_object::minimal::MinimalSequenceType {
736 use crate::type_object::flags::{CollectionElementFlag, CollectionTypeFlag};
737 use crate::type_object::minimal::{
738 CommonCollectionElement, MinimalCollectionElement, MinimalSequenceType,
739 };
740 MinimalSequenceType {
741 collection_flag: CollectionTypeFlag::default(),
742 bound: self.bound,
743 element: MinimalCollectionElement {
744 common: CommonCollectionElement {
745 element_flags: CollectionElementFlag::default(),
746 type_id: self.element.clone(),
747 },
748 },
749 }
750 }
751}
752
753pub struct ArrayBuilder {
755 element: TypeIdentifier,
756 dimensions: Vec<u32>,
757}
758
759impl ArrayBuilder {
760 #[must_use]
762 pub fn build_minimal(&self) -> crate::type_object::minimal::MinimalArrayType {
763 use crate::type_object::flags::{CollectionElementFlag, CollectionTypeFlag};
764 use crate::type_object::minimal::{
765 CommonCollectionElement, MinimalArrayType, MinimalCollectionElement,
766 };
767 MinimalArrayType {
768 collection_flag: CollectionTypeFlag::default(),
769 bound_seq: self.dimensions.clone(),
770 element: MinimalCollectionElement {
771 common: CommonCollectionElement {
772 element_flags: CollectionElementFlag::default(),
773 type_id: self.element.clone(),
774 },
775 },
776 }
777 }
778}
779
780#[derive(Debug, Clone, PartialEq, Eq)]
782pub enum BuilderError {
783 MutableMapExtensibilityNotAllowed,
788}
789
790pub struct MapBuilder {
792 key: TypeIdentifier,
793 value: TypeIdentifier,
794 bound: u32,
795}
796
797impl MapBuilder {
798 pub fn add_map_member(
805 self,
806 ext: Extensibility,
807 ) -> Result<crate::type_object::minimal::MinimalMapType, BuilderError> {
808 if matches!(ext, Extensibility::Mutable) {
809 return Err(BuilderError::MutableMapExtensibilityNotAllowed);
810 }
811 Ok(self.build_minimal())
812 }
813
814 #[must_use]
816 pub fn build_minimal(&self) -> crate::type_object::minimal::MinimalMapType {
817 use crate::type_object::flags::{CollectionElementFlag, CollectionTypeFlag};
818 use crate::type_object::minimal::{
819 CommonCollectionElement, MinimalCollectionElement, MinimalMapType,
820 };
821 let element = MinimalCollectionElement {
822 common: CommonCollectionElement {
823 element_flags: CollectionElementFlag::default(),
824 type_id: self.value.clone(),
825 },
826 };
827 let key = MinimalCollectionElement {
828 common: CommonCollectionElement {
829 element_flags: CollectionElementFlag::default(),
830 type_id: self.key.clone(),
831 },
832 };
833 MinimalMapType {
834 collection_flag: CollectionTypeFlag::default(),
835 bound: self.bound,
836 key,
837 element,
838 }
839 }
840}
841
842pub struct BitmaskBuilder {
848 name: String,
849 bit_bound: u16,
850 flags: Vec<(String, u16)>,
851}
852
853impl BitmaskBuilder {
854 #[must_use]
856 pub fn bit_bound(mut self, bits: u16) -> Self {
857 self.bit_bound = bits;
858 self
859 }
860
861 #[must_use]
863 pub fn flag(mut self, name: impl Into<String>, position: u16) -> Self {
864 self.flags.push((name.into(), position));
865 self
866 }
867
868 #[must_use]
870 pub fn build_minimal(&self) -> crate::type_object::minimal::MinimalBitmaskType {
871 use crate::type_object::flags::{BitflagFlag, BitmaskTypeFlag};
872 use crate::type_object::minimal::{CommonBitflag, MinimalBitflag, MinimalBitmaskType};
873 MinimalBitmaskType {
874 bitmask_flags: BitmaskTypeFlag::default(),
875 bit_bound: self.bit_bound,
876 flag_seq: self
877 .flags
878 .iter()
879 .map(|(n, p)| MinimalBitflag {
880 common: CommonBitflag {
881 position: *p,
882 flags: BitflagFlag::default(),
883 },
884 detail: NameHash::from_name(n),
885 })
886 .collect(),
887 }
888 }
889
890 #[must_use]
892 pub fn build_complete(&self) -> crate::type_object::complete::CompleteBitmaskType {
893 use crate::type_object::common::{
894 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
895 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
896 };
897 use crate::type_object::complete::{CompleteBitflag, CompleteBitmaskType};
898 use crate::type_object::flags::{BitflagFlag, BitmaskTypeFlag};
899 CompleteBitmaskType {
900 bitmask_flags: BitmaskTypeFlag::default(),
901 bit_bound: self.bit_bound,
902 detail: CompleteTypeDetail {
903 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
904 ann_custom: OptionalAppliedAnnotationSeq::default(),
905 type_name: self.name.clone(),
906 },
907 flag_seq: self
908 .flags
909 .iter()
910 .map(|(n, p)| CompleteBitflag {
911 common: crate::type_object::minimal::CommonBitflag {
912 position: *p,
913 flags: BitflagFlag::default(),
914 },
915 detail: CompleteMemberDetail {
916 name: n.clone(),
917 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
918 ann_custom: OptionalAppliedAnnotationSeq::default(),
919 },
920 })
921 .collect(),
922 }
923 }
924
925 #[must_use]
927 pub fn name(&self) -> &str {
928 &self.name
929 }
930}
931
932pub struct BitsetBuilder {
934 name: String,
935 fields: Vec<BitfieldSpec>,
936}
937
938struct BitfieldSpec {
939 name: String,
940 position: u16,
941 bitcount: u8,
942 holder_type: u8,
943}
944
945impl BitsetBuilder {
946 #[must_use]
948 pub fn field(
949 mut self,
950 name: impl Into<String>,
951 position: u16,
952 bitcount: u8,
953 holder_type: u8,
954 ) -> Self {
955 self.fields.push(BitfieldSpec {
956 name: name.into(),
957 position,
958 bitcount,
959 holder_type,
960 });
961 self
962 }
963
964 #[must_use]
966 pub fn build_minimal(&self) -> crate::type_object::minimal::MinimalBitsetType {
967 use crate::type_object::flags::{BitfieldFlag, BitsetTypeFlag};
968 use crate::type_object::minimal::{CommonBitfield, MinimalBitfield, MinimalBitsetType};
969 MinimalBitsetType {
970 bitset_flags: BitsetTypeFlag::default(),
971 field_seq: self
972 .fields
973 .iter()
974 .map(|f| MinimalBitfield {
975 common: CommonBitfield {
976 position: f.position,
977 flags: BitfieldFlag::default(),
978 bitcount: f.bitcount,
979 holder_type: f.holder_type,
980 },
981 name_hash: NameHash::from_name(&f.name),
982 })
983 .collect(),
984 }
985 }
986
987 #[must_use]
989 pub fn build_complete(&self) -> crate::type_object::complete::CompleteBitsetType {
990 use crate::type_object::common::{
991 AppliedBuiltinMemberAnnotations, AppliedBuiltinTypeAnnotations, CompleteMemberDetail,
992 CompleteTypeDetail, OptionalAppliedAnnotationSeq,
993 };
994 use crate::type_object::complete::{CompleteBitfield, CompleteBitsetType};
995 use crate::type_object::flags::{BitfieldFlag, BitsetTypeFlag};
996 CompleteBitsetType {
997 bitset_flags: BitsetTypeFlag::default(),
998 detail: CompleteTypeDetail {
999 ann_builtin: AppliedBuiltinTypeAnnotations::default(),
1000 ann_custom: OptionalAppliedAnnotationSeq::default(),
1001 type_name: self.name.clone(),
1002 },
1003 field_seq: self
1004 .fields
1005 .iter()
1006 .map(|f| CompleteBitfield {
1007 common: crate::type_object::minimal::CommonBitfield {
1008 position: f.position,
1009 flags: BitfieldFlag::default(),
1010 bitcount: f.bitcount,
1011 holder_type: f.holder_type,
1012 },
1013 detail: CompleteMemberDetail {
1014 name: f.name.clone(),
1015 ann_builtin: AppliedBuiltinMemberAnnotations::default(),
1016 ann_custom: OptionalAppliedAnnotationSeq::default(),
1017 },
1018 })
1019 .collect(),
1020 }
1021 }
1022
1023 #[must_use]
1025 pub fn name(&self) -> &str {
1026 &self.name
1027 }
1028}
1029
1030impl TypeObjectBuilder {
1035 #[must_use]
1038 pub fn union_type(name: impl Into<String>, discriminator_type: TypeIdentifier) -> UnionBuilder {
1039 UnionBuilder {
1040 name: name.into(),
1041 extensibility: Extensibility::default(),
1042 discriminator_type,
1043 cases: Vec::new(),
1044 }
1045 }
1046
1047 #[must_use]
1049 pub fn sequence(element: TypeIdentifier, bound: u32) -> SequenceBuilder {
1050 SequenceBuilder { element, bound }
1051 }
1052
1053 #[must_use]
1055 pub fn array(element: TypeIdentifier, dimensions: Vec<u32>) -> ArrayBuilder {
1056 ArrayBuilder {
1057 element,
1058 dimensions,
1059 }
1060 }
1061
1062 #[must_use]
1064 pub fn map(key: TypeIdentifier, value: TypeIdentifier, bound: u32) -> MapBuilder {
1065 MapBuilder { key, value, bound }
1066 }
1067
1068 #[must_use]
1070 pub fn bitmask(name: impl Into<String>) -> BitmaskBuilder {
1071 BitmaskBuilder {
1072 name: name.into(),
1073 bit_bound: 32,
1074 flags: Vec::new(),
1075 }
1076 }
1077
1078 #[must_use]
1080 pub fn bitset(name: impl Into<String>) -> BitsetBuilder {
1081 BitsetBuilder {
1082 name: name.into(),
1083 fields: Vec::new(),
1084 }
1085 }
1086}
1087
1088#[cfg(test)]
1093#[allow(clippy::unwrap_used)]
1094mod tests {
1095 use super::*;
1096 use crate::type_identifier::PrimitiveKind;
1097 use crate::type_object::flags::StructTypeFlag;
1098
1099 #[test]
1100 fn struct_builder_basic_with_two_members() {
1101 let st = TypeObjectBuilder::struct_type("::chat::Chatter")
1102 .member(
1103 "sensor_id",
1104 TypeIdentifier::Primitive(PrimitiveKind::Int64),
1105 |m| m.key(),
1106 )
1107 .member("text", TypeIdentifier::String8Small { bound: 255 }, |m| m)
1108 .build_minimal();
1109
1110 assert_eq!(st.member_seq.len(), 2);
1111 assert_eq!(st.member_seq[0].common.member_id, 1);
1112 assert!(
1113 st.member_seq[0]
1114 .common
1115 .member_flags
1116 .has(StructMemberFlag::IS_KEY)
1117 );
1118 assert_eq!(st.member_seq[1].common.member_id, 2);
1119 assert_eq!(st.member_seq[0].detail, NameHash::from_name("sensor_id"));
1121 assert_eq!(st.member_seq[1].detail, NameHash::from_name("text"));
1122 }
1123
1124 #[test]
1125 fn struct_builder_explicit_ids_respected() {
1126 let st = TypeObjectBuilder::struct_type("::X")
1127 .member("a", TypeIdentifier::Primitive(PrimitiveKind::Int32), |m| {
1128 m.id(100)
1129 })
1130 .member("b", TypeIdentifier::Primitive(PrimitiveKind::Int32), |m| {
1131 m.id(200)
1132 })
1133 .build_minimal();
1134 assert_eq!(st.member_seq[0].common.member_id, 100);
1135 assert_eq!(st.member_seq[1].common.member_id, 200);
1136 }
1137
1138 #[test]
1139 fn mutable_map_extensibility_is_error() {
1140 let res = TypeObjectBuilder::map(
1142 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1143 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1144 10,
1145 )
1146 .add_map_member(Extensibility::Mutable);
1147 assert!(matches!(
1148 res,
1149 Err(BuilderError::MutableMapExtensibilityNotAllowed)
1150 ));
1151 }
1152
1153 #[test]
1154 fn appendable_map_extensibility_is_ok() {
1155 let res = TypeObjectBuilder::map(
1156 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1157 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1158 10,
1159 )
1160 .add_map_member(Extensibility::Appendable);
1161 assert!(res.is_ok());
1162 }
1163
1164 #[test]
1165 fn final_map_extensibility_is_ok() {
1166 let res = TypeObjectBuilder::map(
1167 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1168 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1169 10,
1170 )
1171 .add_map_member(Extensibility::Final);
1172 assert!(res.is_ok());
1173 }
1174
1175 #[test]
1176 fn member_with_explicit_default_used_when_field_missing() {
1177 let st = TypeObjectBuilder::struct_type("::S")
1181 .member("a", TypeIdentifier::Primitive(PrimitiveKind::Int32), |m| {
1182 m.set_member_default("42")
1183 })
1184 .build_complete();
1185 assert_eq!(
1186 st.member_seq[0].detail.ann_builtin.default_value.as_deref(),
1187 Some("42")
1188 );
1189 }
1190
1191 #[test]
1192 fn default_overrides_implicit_zero() {
1193 let st = TypeObjectBuilder::struct_type("::S")
1198 .member("a", TypeIdentifier::Primitive(PrimitiveKind::Int32), |m| {
1199 m.set_member_default("99")
1200 })
1201 .member("b", TypeIdentifier::Primitive(PrimitiveKind::Int32), |m| m)
1202 .build_complete();
1203 assert_eq!(
1204 st.member_seq[0].detail.ann_builtin.default_value.as_deref(),
1205 Some("99")
1206 );
1207 assert_eq!(st.member_seq[1].detail.ann_builtin.default_value, None);
1208 }
1209
1210 #[test]
1211 fn default_value_roundtrips_via_encode_decode() {
1212 use crate::type_object::common::AppliedBuiltinMemberAnnotations;
1213 use alloc::vec;
1214 use zerodds_cdr::{BufferReader, BufferWriter, Endianness};
1215 let ann = AppliedBuiltinMemberAnnotations {
1216 unit: Some("meters".into()),
1217 min: Some(vec![0]),
1218 max: Some(vec![100]),
1219 hash_id: None,
1220 default_value: Some("17".into()),
1221 };
1222 let mut w = BufferWriter::new(Endianness::Little);
1223 ann.encode_into(&mut w).unwrap();
1224 let bytes = w.into_bytes();
1225 let mut r = BufferReader::new(&bytes, Endianness::Little);
1226 let decoded = AppliedBuiltinMemberAnnotations::decode_from(&mut r).unwrap();
1227 assert_eq!(decoded, ann);
1228 }
1229
1230 #[test]
1231 fn struct_builder_extensibility_mutable() {
1232 let st = TypeObjectBuilder::struct_type("::Y")
1233 .extensibility(Extensibility::Mutable)
1234 .build_minimal();
1235 assert!(st.struct_flags.has(StructTypeFlag::IS_MUTABLE));
1236 assert!(!st.struct_flags.has(StructTypeFlag::IS_APPENDABLE));
1237 }
1238
1239 #[test]
1240 fn complete_builder_preserves_names() {
1241 let st = TypeObjectBuilder::struct_type("::sensors::Chatter")
1242 .extensibility(Extensibility::Appendable)
1243 .member(
1244 "sensor_id",
1245 TypeIdentifier::Primitive(PrimitiveKind::Int64),
1246 |m| m.key().unit("celsius"),
1247 )
1248 .build_complete();
1249 assert_eq!(st.header.detail.type_name, "::sensors::Chatter");
1250 assert_eq!(st.member_seq[0].detail.name, "sensor_id");
1251 assert_eq!(
1252 st.member_seq[0].detail.ann_builtin.unit.as_deref(),
1253 Some("celsius")
1254 );
1255 }
1256
1257 #[test]
1258 fn struct_builder_autoid_hash_collision_free_for_distinct_names() {
1259 let st = TypeObjectBuilder::struct_type("::H")
1260 .autoid_hash()
1261 .member(
1262 "alpha",
1263 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1264 |m| m,
1265 )
1266 .member(
1267 "beta",
1268 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1269 |m| m,
1270 )
1271 .build_minimal();
1272 assert!(st.struct_flags.has(StructTypeFlag::IS_AUTOID_HASH));
1273 assert_ne!(
1274 st.member_seq[0].common.member_id,
1275 st.member_seq[1].common.member_id
1276 );
1277 }
1278
1279 #[test]
1280 fn enum_builder_roundtrip_ready() {
1281 let e = TypeObjectBuilder::enum_type("::Color")
1282 .bit_bound(16)
1283 .default_literal("RED", 0)
1284 .literal("GREEN", 1)
1285 .literal("BLUE", 2)
1286 .build_minimal();
1287 assert_eq!(e.header.common.bit_bound, 16);
1288 assert_eq!(e.literal_seq.len(), 3);
1289 assert!(e.literal_seq[0].common.flags.0 & EnumLiteralFlag::IS_DEFAULT_LITERAL != 0);
1290 }
1291
1292 #[test]
1293 fn alias_builder_minimal_and_complete() {
1294 let a_min =
1295 TypeObjectBuilder::alias("::Count", TypeIdentifier::Primitive(PrimitiveKind::UInt64))
1296 .build_minimal();
1297 assert!(matches!(
1298 a_min.body.common.related_type,
1299 TypeIdentifier::Primitive(PrimitiveKind::UInt64)
1300 ));
1301
1302 let a_cmp =
1303 TypeObjectBuilder::alias("::Count", TypeIdentifier::Primitive(PrimitiveKind::UInt64))
1304 .build_complete();
1305 assert_eq!(a_cmp.header.detail.type_name, "::Count");
1306 }
1307
1308 #[test]
1313 fn union_builder_minimal_with_two_cases_and_default() {
1314 let u = TypeObjectBuilder::union_type(
1315 "::Shape",
1316 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1317 )
1318 .case(
1319 "circle",
1320 TypeIdentifier::Primitive(PrimitiveKind::Float64),
1321 alloc::vec![1, 2],
1322 )
1323 .default_case("other", TypeIdentifier::String8Small { bound: 64 })
1324 .build_minimal();
1325 assert_eq!(u.member_seq.len(), 2);
1326 assert_eq!(u.member_seq[0].common.label_seq, alloc::vec![1, 2]);
1327 assert!(
1329 u.member_seq[1].common.member_flags.0
1330 & crate::type_object::flags::UnionMemberFlag::IS_DEFAULT
1331 != 0
1332 );
1333 }
1334
1335 #[test]
1336 fn union_builder_complete_preserves_names_and_extensibility() {
1337 let u = TypeObjectBuilder::union_type(
1338 "::Shape",
1339 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1340 )
1341 .extensibility(Extensibility::Mutable)
1342 .case(
1343 "a",
1344 TypeIdentifier::Primitive(PrimitiveKind::Int32),
1345 alloc::vec![1],
1346 )
1347 .build_complete();
1348 assert_eq!(u.header.detail.type_name, "::Shape");
1349 assert_eq!(u.member_seq[0].detail.name, "a");
1350 assert_eq!(
1351 u.union_flags.0 & StructTypeFlag::IS_MUTABLE,
1352 StructTypeFlag::IS_MUTABLE
1353 );
1354 }
1355
1356 #[test]
1357 fn sequence_builder_minimal() {
1358 let s = TypeObjectBuilder::sequence(TypeIdentifier::Primitive(PrimitiveKind::Int16), 100)
1359 .build_minimal();
1360 assert_eq!(s.bound, 100);
1361 assert!(matches!(
1362 s.element.common.type_id,
1363 TypeIdentifier::Primitive(PrimitiveKind::Int16)
1364 ));
1365 }
1366
1367 #[test]
1368 fn array_builder_3d() {
1369 let a = TypeObjectBuilder::array(
1370 TypeIdentifier::Primitive(PrimitiveKind::Float32),
1371 alloc::vec![4, 4, 4],
1372 )
1373 .build_minimal();
1374 assert_eq!(a.bound_seq, alloc::vec![4, 4, 4]);
1375 }
1376
1377 #[test]
1378 fn map_builder_string_to_int() {
1379 let m = TypeObjectBuilder::map(
1380 TypeIdentifier::String8Small { bound: 64 },
1381 TypeIdentifier::Primitive(PrimitiveKind::Int64),
1382 1_000,
1383 )
1384 .build_minimal();
1385 assert_eq!(m.bound, 1_000);
1386 assert!(matches!(
1387 m.key.common.type_id,
1388 TypeIdentifier::String8Small { bound: 64 }
1389 ));
1390 }
1391
1392 #[test]
1393 fn bitmask_builder_three_flags() {
1394 let b = TypeObjectBuilder::bitmask("::Permissions")
1395 .bit_bound(32)
1396 .flag("READ", 0)
1397 .flag("WRITE", 1)
1398 .flag("EXEC", 2)
1399 .build_minimal();
1400 assert_eq!(b.bit_bound, 32);
1401 assert_eq!(b.flag_seq.len(), 3);
1402 assert_eq!(b.flag_seq[0].common.position, 0);
1403 assert_eq!(b.flag_seq[2].common.position, 2);
1404 }
1405
1406 #[test]
1407 fn bitset_builder_two_fields() {
1408 let b = TypeObjectBuilder::bitset("::Packed")
1409 .field("header", 0, 4, 0x07) .field("body", 4, 28, 0x07)
1411 .build_minimal();
1412 assert_eq!(b.field_seq.len(), 2);
1413 assert_eq!(b.field_seq[0].common.bitcount, 4);
1414 assert_eq!(b.field_seq[1].common.position, 4);
1415 }
1416
1417 #[test]
1418 fn bitmask_builder_complete_preserves_names() {
1419 let b = TypeObjectBuilder::bitmask("::Perm")
1420 .bit_bound(16)
1421 .flag("READ", 0)
1422 .flag("WRITE", 1)
1423 .build_complete();
1424 assert_eq!(b.detail.type_name, "::Perm");
1425 assert_eq!(b.bit_bound, 16);
1426 assert_eq!(b.flag_seq.len(), 2);
1427 assert_eq!(b.flag_seq[0].detail.name, "READ");
1428 assert_eq!(b.flag_seq[1].detail.name, "WRITE");
1429 }
1430
1431 #[test]
1432 fn bitset_builder_complete_preserves_names() {
1433 let b = TypeObjectBuilder::bitset("::Packed")
1434 .field("header", 0, 4, 0x07)
1435 .field("body", 4, 28, 0x07)
1436 .build_complete();
1437 assert_eq!(b.detail.type_name, "::Packed");
1438 assert_eq!(b.field_seq.len(), 2);
1439 assert_eq!(b.field_seq[0].detail.name, "header");
1440 assert_eq!(b.field_seq[1].detail.name, "body");
1441 }
1442}