zerodds_types/dynamic/
collection.rs1use alloc::vec;
17
18use super::descriptor::{MemberDescriptor, TypeDescriptor, TypeKind};
19use super::type_::{DynamicType, DynamicTypeInner, DynamicTypeMember};
20
21const ELEMENT_MEMBER: &str = "@element";
23
24#[must_use]
27pub fn sequence_of(element: DynamicType, bound: u32) -> DynamicType {
28 sequence_named("seq", element, bound)
29}
30
31#[must_use]
34pub fn sequence_named(name: &str, element: DynamicType, bound: u32) -> DynamicType {
35 let desc = TypeDescriptor::sequence(name, element.descriptor().clone(), bound);
36 with_element(desc, element)
37}
38
39#[must_use]
42pub fn array_of(element: DynamicType, dims: alloc::vec::Vec<u32>, name: &str) -> DynamicType {
43 let desc = TypeDescriptor::array(name, element.descriptor().clone(), dims);
44 with_element(desc, element)
45}
46
47fn with_element(desc: TypeDescriptor, element: DynamicType) -> DynamicType {
48 let mut md = MemberDescriptor::new(ELEMENT_MEMBER, 0, element.descriptor().clone());
49 md.index = 0;
50 DynamicType::from_inner(DynamicTypeInner {
51 descriptor: desc,
52 members: vec![DynamicTypeMember {
53 descriptor: md,
54 member_type: element,
55 }],
56 })
57}
58
59const KEY_MEMBER: &str = "@key";
62const VALUE_MEMBER: &str = "@value";
63
64#[must_use]
67pub fn map_of(key: DynamicType, value: DynamicType, bound: u32, name: &str) -> DynamicType {
68 let desc = TypeDescriptor::map(
69 name,
70 key.descriptor().clone(),
71 value.descriptor().clone(),
72 bound,
73 );
74 let mut km = MemberDescriptor::new(KEY_MEMBER, 0, key.descriptor().clone());
75 km.index = 0;
76 let mut vm = MemberDescriptor::new(VALUE_MEMBER, 1, value.descriptor().clone());
77 vm.index = 1;
78 DynamicType::from_inner(DynamicTypeInner {
79 descriptor: desc,
80 members: vec![
81 DynamicTypeMember {
82 descriptor: km,
83 member_type: key,
84 },
85 DynamicTypeMember {
86 descriptor: vm,
87 member_type: value,
88 },
89 ],
90 })
91}
92
93#[must_use]
97pub fn resolved_element(ty: &DynamicType) -> Option<&DynamicType> {
98 if matches!(ty.kind(), TypeKind::Sequence | TypeKind::Array) {
99 ty.member_by_index(0).map(|m| m.dynamic_type())
100 } else {
101 None
102 }
103}
104
105#[must_use]
107pub fn resolved_map_key(ty: &DynamicType) -> Option<&DynamicType> {
108 if ty.kind() == TypeKind::Map {
109 ty.member_by_index(0).map(|m| m.dynamic_type())
110 } else {
111 None
112 }
113}
114
115#[must_use]
117pub fn resolved_map_value(ty: &DynamicType) -> Option<&DynamicType> {
118 if ty.kind() == TypeKind::Map {
119 ty.member_by_index(1).map(|m| m.dynamic_type())
120 } else {
121 None
122 }
123}
124
125#[cfg(test)]
126#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
127mod tests {
128 use super::*;
129 use crate::dynamic::builder::DynamicTypeBuilderFactory as F;
130
131 #[test]
132 fn sequence_of_struct_retains_element() {
133 let mut b = F::create_struct("E");
134 b.add_struct_member("a", 0, TypeDescriptor::primitive(TypeKind::Int32, "int32"))
135 .unwrap();
136 let elem = b.build().unwrap();
137 let seq = sequence_of(elem, 0);
138 assert_eq!(seq.kind(), TypeKind::Sequence);
139 let re = resolved_element(&seq).expect("resolved element");
140 assert_eq!(re.kind(), TypeKind::Structure);
141 assert_eq!(re.member_count(), 1);
142 }
143
144 #[test]
145 fn scalar_sequence_has_no_resolved_element() {
146 let desc = TypeDescriptor::sequence(
148 "seq",
149 TypeDescriptor::primitive(TypeKind::Int32, "int32"),
150 0,
151 );
152 let ty = F::create_type(desc).unwrap().build().unwrap();
153 assert!(resolved_element(&ty).is_none());
154 }
155}