1use crate::ArrayReader;
2use crate::ir::{self, TyKind};
3
4#[derive(Debug, Clone, Copy)]
6pub struct Shape {
7 pub items: Option<usize>,
9 pub fields: Option<usize>,
12}
13
14pub fn get_shape(data: &[u8], ty: &ir::Ty, ty_defs: &[ir::TyDef]) -> Shape {
19 let ty_mat = resolve_ty(ty, ty_defs);
20 match &ty_mat.kind {
21 TyKind::Array(item_ty) => {
22 let (_, items) = ArrayReader::<&[u8]>::read_head(data);
23 Shape {
24 items: Some(items),
25 fields: get_shape_tuple(item_ty, ty_defs),
26 }
27 }
28 TyKind::Tuple(_) => Shape {
29 items: None,
30 fields: get_shape_tuple(ty_mat, ty_defs),
31 },
32 _ => Shape {
33 items: None,
34 fields: None,
35 },
36 }
37}
38
39pub fn get_shape_tuple(ty: &ir::Ty, ty_defs: &[ir::TyDef]) -> Option<usize> {
40 let ty_mat = resolve_ty(ty, ty_defs);
41 match &ty_mat.kind {
42 TyKind::Tuple(fields) => Some(
43 fields
44 .iter()
45 .map(|f| get_shape_tuple(&f.ty, ty_defs).unwrap_or(1))
46 .sum(),
47 ),
48 _ => None,
49 }
50}
51
52fn resolve_ty<'a>(ty: &'a ir::Ty, ty_defs: &'a [ir::TyDef]) -> &'a ir::Ty {
53 if let TyKind::Ident(path) = &ty.kind
54 && let Some(def) = ty_defs.iter().find(|d| &d.name == path)
55 {
56 return resolve_ty(&def.ty, ty_defs);
57 }
58 ty
59}