use std::{
fmt::Debug,
io::{Read, Seek},
+ iter::{repeat, zip},
ops::Deref,
str::FromStr,
sync::Arc,
dimension
})
.collect::<Vec<_>>();
- let dimensions = match self.axes.decode(dimensions) {
- Ok(dimensions) => dimensions,
- Err((warning, dimensions)) => {
+ let axes = self
+ .axes
+ .decode(dimensions.len())
+ .unwrap_or_else(|warning| {
warn(warning);
- dimensions
- .into_iter()
- .map(|dimension| (Axis3::Y, dimension))
- .collect()
- }
- };
- let pivot_table = PivotTable::new(dimensions)
+ vec![Axis3::Y; dimensions.len()]
+ });
+ let pivot_table = PivotTable::new(zip(axes, dimensions))
.with_style(PivotTableStyle {
look: Arc::new(self.decode_look(encoding)),
rotate_inner_column_labels: self.header.rotate_inner_column_labels,
}
impl Axes {
- fn decode(
- &self,
- dimensions: Vec<pivot::Dimension>,
- ) -> Result<Vec<(Axis3, pivot::Dimension)>, (LightWarning, Vec<pivot::Dimension>)> {
- let n = self.layers.len() + self.rows.len() + self.columns.len();
- if n != dimensions.len() {
- return Err((
- LightWarning::WrongAxisCount {
- expected: dimensions.len(),
- actual: n,
- n_layers: self.layers.len(),
- n_rows: self.rows.len(),
- n_columns: self.columns.len(),
- },
- dimensions,
- ));
+ fn decode(&self, n: usize) -> Result<Vec<Axis3>, LightWarning> {
+ let actual = self.layers.len() + self.rows.len() + self.columns.len();
+ if actual != n {
+ return Err(LightWarning::WrongAxisCount {
+ expected: n,
+ actual,
+ n_layers: self.layers.len(),
+ n_rows: self.rows.len(),
+ n_columns: self.columns.len(),
+ });
}
+ let mut axes = vec![None; n];
+
fn axis_dims(axis: Axis3, dimensions: &[u32]) -> impl Iterator<Item = (Axis3, usize)> {
- dimensions.iter().map(move |d| (axis, *d as usize))
+ repeat(axis).zip(dimensions.iter().copied().map(|x| x.try_into().unwrap()))
}
- let mut dimensions = dimensions.into_iter().map(Some).collect::<Vec<_>>();
- let mut output = Vec::with_capacity(n);
-
for (axis, index) in axis_dims(Axis3::Z, &self.layers)
.chain(axis_dims(Axis3::Y, &self.rows))
.chain(axis_dims(Axis3::X, &self.columns))
{
- let result = dimensions
- .get_mut(index)
- .ok_or(LightWarning::InvalidDimensionIndex { index, n })
- .and_then(|dimension| {
- dimension
- .take()
- .ok_or(LightWarning::DuplicateDimensionIndex(index))
- });
- match result {
- Ok(dimension) => output.push((axis, dimension)),
- Err(error) => {
- let dimensions = dimensions
- .into_iter()
- .flatten()
- .chain(output.into_iter().map(|(_axis, dimension)| dimension))
- .collect();
- return Err((error, dimensions));
- }
+ match axes.get_mut(index) {
+ None => return Err(LightWarning::InvalidDimensionIndex { index, n }),
+ Some(Some(_)) => return Err(LightWarning::DuplicateDimensionIndex(index)),
+ Some(inner) => *inner = Some(axis),
}
}
- Ok(output)
+
+ Ok(axes.into_iter().flatten().collect())
}
}