use crate::ArrayReader;
use crate::ir::{self, TyKind};
#[derive(Debug, Clone, Copy)]
pub struct Shape {
pub items: Option<usize>,
pub fields: Option<usize>,
}
pub fn get_shape(data: &[u8], ty: &ir::Ty, ty_defs: &[ir::TyDef]) -> Shape {
let ty_mat = get_ty_mat(ty, ty_defs);
match &ty_mat.kind {
TyKind::Array(item_ty) => {
let (_, items) = ArrayReader::<&[u8]>::read_head(data);
Shape {
items: Some(items),
fields: get_shape_tuple(item_ty, ty_defs),
}
}
TyKind::Tuple(_) => Shape {
items: None,
fields: get_shape_tuple(ty_mat, ty_defs),
},
_ => Shape {
items: None,
fields: None,
},
}
}
pub fn get_shape_tuple(ty: &ir::Ty, ty_defs: &[ir::TyDef]) -> Option<usize> {
let ty_mat = get_ty_mat(ty, ty_defs);
match &ty_mat.kind {
TyKind::Tuple(fields) => Some(
fields
.iter()
.map(|f| get_shape_tuple(&f.ty, ty_defs).unwrap_or(1))
.sum(),
),
_ => None,
}
}
fn get_ty_mat<'a>(mut ty: &'a ir::Ty, ty_defs: &'a [ir::TyDef]) -> &'a ir::Ty {
while let TyKind::Ident(path) = &ty.kind {
if ir::TyStd::try_new(path).is_some() {
return ty;
}
let Some(def) = ty_defs.iter().find(|d| &d.name == path) else {
return ty;
};
ty = &def.ty;
}
ty
}