};
use cairo::{Context, RecordingSurface};
+use enum_iterator::all;
use enum_map::{Enum, EnumMap, enum_map};
use indexmap::{IndexMap, IndexSet};
use itertools::Itertools;
.iter()
.map(|raw| Element::new(raw, locale, series, bin_widths, axis_domains, styles))
.collect::<Result<Vec<_>, _>>()?;
- 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())
{
{
*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;
}
}
- let axis2 = dimensions
- .get(index)
+ let axis2 = dimensions[axis]
+ .as_ref()
.and_then(|dimension| dimension.axis.first());
axis_domains[axis] = AxisDomain {
domain,
&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,
);
}
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()
}
}
style: String,
}
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase")]
+#[derive(Debug)]
struct Coordinates {
- #[serde(rename = "$value")]
- #[serde(default)]
- children: Vec<CoordinatesChild>,
+ dimensions: EnumMap<Axis3, Option<Dimension>>,
}
-impl Coordinates {
- fn dimensions(&self) -> impl Iterator<Item = &Dimension> {
- self.children.iter().filter_map(|child| match child {
+impl<'de> Deserialize<'de> for Coordinates {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ #[derive(Deserialize, Debug)]
+ #[serde(rename_all = "camelCase")]
+ struct RawCoordinates {
+ #[serde(rename = "$value")]
+ #[serde(default)]
+ children: Vec<CoordinatesChild>,
+ }
+
+ #[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 {