use std::collections::HashMap;
use hdf5_reader::group::Group;
use crate::error::Result;
use crate::types::NcDimension;
fn leaf_name(name: &str) -> &str {
name.rsplit('/').next().unwrap_or(name)
}
pub fn extract_dimensions(
group: &Group<'_>,
) -> Result<(Vec<NcDimension>, HashMap<u64, NcDimension>)> {
let datasets = match group.datasets() {
Ok(ds) => ds,
Err(_) => return Ok((Vec::new(), HashMap::new())),
};
extract_dimensions_from_datasets(&datasets)
}
pub fn extract_dimensions_from_datasets(
datasets: &[hdf5_reader::Dataset<'_>],
) -> Result<(Vec<NcDimension>, HashMap<u64, NcDimension>)> {
let mut dims: Vec<(Option<i64>, NcDimension, u64)> = Vec::new();
for ds in datasets {
let is_dim_scale = ds
.attribute("CLASS")
.ok()
.and_then(|attr| attr.read_string().ok())
.map(|s| s == "DIMENSION_SCALE")
.unwrap_or(false);
if !is_dim_scale {
continue;
}
let name = ds
.attribute("NAME")
.ok()
.and_then(|attr| attr.read_string().ok())
.map(|s| {
if s.starts_with("This is a netCDF dimension but not a netCDF variable") {
leaf_name(ds.name()).to_string()
} else {
s
}
})
.unwrap_or_else(|| leaf_name(ds.name()).to_string());
let shape = ds.shape();
let size = if shape.is_empty() { 0 } else { shape[0] };
let is_unlimited = ds
.max_dims()
.is_some_and(|md| !md.is_empty() && md[0] == u64::MAX);
let dimid = ds
.attribute("_Netcdf4Dimid")
.ok()
.and_then(|attr| attr.read_scalar::<i32>().ok())
.map(|id| id as i64);
let address = ds.address();
dims.push((
dimid,
NcDimension {
name,
size,
is_unlimited,
},
address,
));
}
dims.sort_by_key(|(id, _, _)| id.unwrap_or(i64::MAX));
let addr_map: HashMap<u64, NcDimension> =
dims.iter().map(|(_, d, addr)| (*addr, d.clone())).collect();
let dim_list: Vec<NcDimension> = dims.into_iter().map(|(_, d, _)| d).collect();
Ok((dim_list, addr_map))
}