From d6e0be6b8e3c109bd8232fc44fde35ed6ab8f208 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 19 Aug 2026 17:39:41 -0700 Subject: [PATCH] better types --- rust/pspp/src/spv/read/graph.rs | 72 +++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/rust/pspp/src/spv/read/graph.rs b/rust/pspp/src/spv/read/graph.rs index 45a12e0930..2d4d959c1d 100644 --- a/rust/pspp/src/spv/read/graph.rs +++ b/rust/pspp/src/spv/read/graph.rs @@ -29,6 +29,7 @@ use std::{ }; use cairo::{Context, RecordingSurface}; +use enum_iterator::all; use enum_map::{Enum, EnumMap, enum_map}; use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; @@ -376,9 +377,9 @@ impl Visualization { .iter() .map(|raw| Element::new(raw, locale, series, bin_widths, axis_domains, styles)) .collect::, _>>()?; - let dimensions = graph.coordinates.dimensions().collect_vec(); - for (index, axis) in [Axis3::X, Axis3::Y, Axis3::Z].into_iter().enumerate() { - let mut domain = if let Some(dimension) = dimensions.get(index) + let dimensions = &graph.coordinates.dimensions; + for axis in all() { + let mut domain = if let Some(dimension) = &dimensions[axis] && let Some(domain_name) = &dimension.domain && let Some(domain) = domains.get(domain_name.as_str()) { @@ -447,7 +448,7 @@ impl Visualization { { *max = Some(0.0); } - if let Some(dimension) = dimensions.get(index) { + if let Some(dimension) = &dimensions[axis] { let mmin = min.unwrap(); let mmax = max.unwrap(); let range = mmax - mmin; @@ -460,8 +461,8 @@ impl Visualization { } } - let axis2 = dimensions - .get(index) + let axis2 = dimensions[axis] + .as_ref() .and_then(|dimension| dimension.axis.first()); axis_domains[axis] = AxisDomain { domain, @@ -647,7 +648,7 @@ impl Visualization { &faceting[axis], &axis_domains[axis.into()], rect.0[axis].length() - heading_heights[!axis], - graph.axis_dimension(axis), + graph.axis_dimension(axis.into()), &font_metrics, axis == Axis2::Y, ); @@ -2792,18 +2793,15 @@ impl Graph { } fn x_dimension(&self) -> Option<&Dimension> { - self.coordinates.dimensions().next() + self.axis_dimension(Axis3::X) } fn y_dimension(&self) -> Option<&Dimension> { - self.coordinates.dimensions().skip(1).next() + self.axis_dimension(Axis3::Y) } - fn axis_dimension(&self, axis: Axis2) -> Option<&Dimension> { - match axis { - Axis2::X => self.x_dimension(), - Axis2::Y => self.y_dimension(), - } + fn axis_dimension(&self, axis: Axis3) -> Option<&Dimension> { + self.coordinates.dimensions[axis].as_ref() } } @@ -3553,31 +3551,43 @@ struct SetFrameStyle { style: String, } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] +#[derive(Debug)] struct Coordinates { - #[serde(rename = "$value")] - #[serde(default)] - children: Vec, + dimensions: EnumMap>, } -impl Coordinates { - fn dimensions(&self) -> impl Iterator { - self.children.iter().filter_map(|child| match child { +impl<'de> Deserialize<'de> for Coordinates { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize, Debug)] + #[serde(rename_all = "camelCase")] + struct RawCoordinates { + #[serde(rename = "$value")] + #[serde(default)] + children: Vec, + } + + #[derive(Deserialize, Debug)] + #[serde(rename_all = "camelCase")] + enum CoordinatesChild { + Dimension(Dimension), + #[serde(other)] + Other, + } + + let raw = RawCoordinates::deserialize(deserializer)?; + let mut dimensions = raw.children.into_iter().filter_map(|child| match child { CoordinatesChild::Dimension(dimension) => Some(dimension), CoordinatesChild::Other => None, - }) + }); + let dimensions = + EnumMap::from_array([dimensions.next(), dimensions.next(), dimensions.next()]); + Ok(Self { dimensions }) } } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -enum CoordinatesChild { - Dimension(Dimension), - #[serde(other)] - Other, -} - #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct Dimension { -- 2.47.3