use alloc::vec;
use super::descriptor::{MemberDescriptor, TypeDescriptor, TypeKind};
use super::type_::{DynamicType, DynamicTypeInner, DynamicTypeMember};
const ELEMENT_MEMBER: &str = "@element";
#[must_use]
pub fn sequence_of(element: DynamicType, bound: u32) -> DynamicType {
let desc = TypeDescriptor::sequence("seq", element.descriptor().clone(), bound);
with_element(desc, element)
}
#[must_use]
pub fn array_of(element: DynamicType, dims: alloc::vec::Vec<u32>, name: &str) -> DynamicType {
let desc = TypeDescriptor::array(name, element.descriptor().clone(), dims);
with_element(desc, element)
}
fn with_element(desc: TypeDescriptor, element: DynamicType) -> DynamicType {
let mut md = MemberDescriptor::new(ELEMENT_MEMBER, 0, element.descriptor().clone());
md.index = 0;
DynamicType::from_inner(DynamicTypeInner {
descriptor: desc,
members: vec![DynamicTypeMember {
descriptor: md,
member_type: element,
}],
})
}
#[must_use]
pub fn resolved_element(ty: &DynamicType) -> Option<&DynamicType> {
if matches!(ty.kind(), TypeKind::Sequence | TypeKind::Array) {
ty.member_by_index(0).map(|m| m.dynamic_type())
} else {
None
}
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
use crate::dynamic::builder::DynamicTypeBuilderFactory as F;
#[test]
fn sequence_of_struct_retains_element() {
let mut b = F::create_struct("E");
b.add_struct_member("a", 0, TypeDescriptor::primitive(TypeKind::Int32, "int32"))
.unwrap();
let elem = b.build().unwrap();
let seq = sequence_of(elem, 0);
assert_eq!(seq.kind(), TypeKind::Sequence);
let re = resolved_element(&seq).expect("resolved element");
assert_eq!(re.kind(), TypeKind::Structure);
assert_eq!(re.member_count(), 1);
}
#[test]
fn scalar_sequence_has_no_resolved_element() {
let desc = TypeDescriptor::sequence(
"seq",
TypeDescriptor::primitive(TypeKind::Int32, "int32"),
0,
);
let ty = F::create_type(desc).unwrap().build().unwrap();
assert!(resolved_element(&ty).is_none());
}
}