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