use serde::{Deserialize, Serialize};
use crate::dimension::Dimensions;
use crate::error::{NetCdfError, Result};
use crate::variable::Variable;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BoundsVariable {
pub name: String,
pub coordinate_variable: String,
pub num_vertices: usize,
}
impl BoundsVariable {
#[must_use]
pub fn new(
name: impl Into<String>,
coordinate_variable: impl Into<String>,
num_vertices: usize,
) -> Self {
Self {
name: name.into(),
coordinate_variable: coordinate_variable.into(),
num_vertices,
}
}
pub fn validate(
&self,
coord_var: &Variable,
bounds_var: &Variable,
dimensions: &Dimensions,
) -> Result<()> {
let coord_dims = coord_var.dimension_names();
let bounds_dims = bounds_var.dimension_names();
if bounds_dims.len() != coord_dims.len() + 1 {
return Err(NetCdfError::CfConventionsError(format!(
"Bounds variable '{}' should have {} dimensions (coordinate dimensions + 1), found {}",
self.name,
coord_dims.len() + 1,
bounds_dims.len()
)));
}
for (i, dim) in coord_dims.iter().enumerate() {
if i < bounds_dims.len() && bounds_dims[i] != *dim {
return Err(NetCdfError::CfConventionsError(format!(
"Bounds variable '{}' dimension mismatch at position {}: expected '{}', found '{}'",
self.name, i, dim, bounds_dims[i]
)));
}
}
if let Some(last_dim) = bounds_dims.last() {
if let Some(dim) = dimensions.get(last_dim) {
if dim.len() != self.num_vertices {
return Err(NetCdfError::CfConventionsError(format!(
"Bounds variable '{}' vertex dimension should have {} vertices, found {}",
self.name,
self.num_vertices,
dim.len()
)));
}
}
}
Ok(())
}
}