From: Ben Pfaff Date: Tue, 25 Aug 2026 17:35:26 +0000 (-0700) Subject: cleanup X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e7f19bee40827b828b59694e2bd374c44959b943;p=pspp cleanup --- diff --git a/rust/doc/src/spv/graphs.md b/rust/doc/src/spv/graphs.md index 0013e94147..dcb2580155 100644 --- a/rust/doc/src/spv/graphs.md +++ b/rust/doc/src/spv/graphs.md @@ -472,11 +472,17 @@ axisTransformParameter `majorTicks` requests drawing the axis itself and tick marks and labels. When the axis is faceted, the axis can either be drawn just -once or separately in each cell: +once or separately in each cell, according to the rules below, in +order of decreasing priority: - If the dimension has a polar transform, then the axis is drawn in every cell (because there's no reasonable way to draw it just once). +- If the `axis` specifies `repeat="never"`, then the axis is drawn + just once. (This can produce deceptive results if `faceting` + specifies `method="nest"`, since in that case different facet cells + might have different axes.) + - If `faceting` specifies `method="nest"`, then the axis is drawn in every cell because each cell has a different axis. diff --git a/rust/pspp/src/spv/read.rs b/rust/pspp/src/spv/read.rs index 01186a64a5..1434a9f7c0 100644 --- a/rust/pspp/src/spv/read.rs +++ b/rust/pspp/src/spv/read.rs @@ -13,7 +13,6 @@ // // You should have received a copy of the GNU General Public License along with // this program. If not, see . -#![allow(dead_code)] use std::{ fmt::Display, fs::File, diff --git a/rust/pspp/src/spv/read/graph.rs b/rust/pspp/src/spv/read/graph.rs index 004b947179..dbdea52f6e 100644 --- a/rust/pspp/src/spv/read/graph.rs +++ b/rust/pspp/src/spv/read/graph.rs @@ -50,7 +50,6 @@ use svg::{ use crate::{ data::Datum, - format::{Type, UncheckedFormat}, locale::{Item, Locale, data::EN}, output::{ SpvGraphMembers, SpvInfo, SpvMembers, @@ -380,7 +379,7 @@ impl Visualization { 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_name) = &dimension._domain && let Some(domain) = domains.get(domain_name.as_str()) { Some(domain.clone()) @@ -468,7 +467,7 @@ impl Visualization { domain, formatter: formatter.unwrap_or_else(|| Formatter::default_for_locale(locale)), axis: axis2, - label: axis2.and_then(|axis| axis.label.as_ref()), + _label: axis2.and_then(|axis| axis.label.as_ref()), major_ticks: axis2.and_then(|axis| axis.major_ticks.as_ref()), }; } @@ -1158,10 +1157,10 @@ where #[derive(Clone)] struct Series { pub name: String, - label: Option, - short_label: Option, - weight: bool, - key: bool, + _label: Option, + _short_label: Option, + _weight: bool, + _key: bool, categorical: bool, values: Vec, unique_values: Vec, @@ -1196,10 +1195,10 @@ impl Series { }; Self { name, - label: None, - short_label: None, - weight: false, - key: false, + _label: None, + _short_label: None, + _weight: false, + _key: false, categorical, values, unique_values, @@ -1207,7 +1206,10 @@ impl Series { } } fn with_label(self, label: Option) -> Self { - Self { label, ..self } + Self { + _label: label, + ..self + } } } @@ -1220,24 +1222,24 @@ struct DelimitedFileSource { /// Always "UTF-8" in the corpus. #[serde(rename = "@encoding")] - pub encoding: String, + pub _encoding: String, /// A filename or URI-like string that probably names on a file on the host /// of the person who created the graph. #[serde(rename = "@fileName")] - pub file_name: Option, + pub _file_name: Option, #[serde(rename = "@missing")] - pub missing: DelimitedFileSourceMissing, + pub _missing: DelimitedFileSourceMissing, } impl Default for DelimitedFileSource { fn default() -> Self { Self { id: String::new(), - encoding: String::from("UTF-8"), - file_name: None, - missing: DelimitedFileSourceMissing::default(), + _encoding: String::from("UTF-8"), + _file_name: None, + _missing: DelimitedFileSourceMissing::default(), } } } @@ -1373,17 +1375,6 @@ struct SourceVariable { string_format: Option, } -impl SourceVariable { - fn affixes(&self) -> &[Affix] { - if let Some(format) = &self.format { - &format.affixes - } else if let Some(string_format) = &self.string_format { - &string_format.affixes - } else { - &[] - } - } -} impl Variable for SourceVariable { fn decode<'a>( &'a self, @@ -1543,7 +1534,7 @@ struct AxisDomain<'a> { domain: Domain, formatter: Formatter, axis: Option<&'a Axis>, - label: Option<&'a Label>, + _label: Option<&'a Label>, major_ticks: Option<&'a MajorTicks>, } @@ -1553,7 +1544,7 @@ impl<'a> AxisDomain<'a> { domain: Domain::default(), formatter: Formatter::default_for_locale(locale), axis: None, - label: None, + _label: None, major_ticks: None, } } @@ -1640,15 +1631,6 @@ impl Domain { exact: false, } } - fn is_interval(&self) -> bool { - matches!(self, Self::Interval { .. }) - } - fn lookup_categorical(&self, value: &Datum) -> Option { - match self { - Domain::Categorical { values } => values.get_index_of(value), - _ => None, - } - } fn lookup(&self, value: &Datum) -> Option { self.lookup_range(value) .map(|range| range.start.midpoint(range.end)) @@ -1690,7 +1672,7 @@ struct CategoricalDomain { id: String, #[serde(default, rename = "@date")] - date: bool, + _date: bool, #[serde(default, rename = "$value")] children: Vec, @@ -1841,7 +1823,7 @@ struct IntervalDomain { id: String, #[serde(default, rename = "@date")] - date: bool, + _date: bool, #[serde(default, rename = "$value")] children: Vec, @@ -1894,7 +1876,7 @@ impl RawDomain for IntervalDomain { enum IntervalDomainChild { Range(IntervalRange), VariableReference(VariableReference), - Format(Format), + Format(#[allow(dead_code)] Format), } impl IntervalDomainChild { @@ -1969,7 +1951,7 @@ struct StringFormat { #[serde(default, rename = "relabel")] relabels: Vec, #[serde(default, rename = "affix")] - affixes: Vec, + _affixes: Vec, } impl StringFormat { @@ -1986,9 +1968,9 @@ impl StringFormat { #[serde(rename_all = "camelCase")] struct Format { #[serde(rename = "@tryStringsAsNumbers")] - try_strings_as_numbers: Option, + _try_strings_as_numbers: Option, #[serde(rename = "@relabelsArePreformatted")] - relabels_are_preformatted: Option, + _relabels_are_preformatted: Option, #[serde(rename = "@separatorChars")] separator_chars: Option, #[serde(rename = "@hiddenseparator")] @@ -2031,7 +2013,7 @@ struct Format { #[serde(rename = "@mdyOrder")] mdy_order: Option, #[serde(rename = "@dayOfMonthPadding")] - day_of_month_padding: Option, + _day_of_month_padding: Option, #[serde(rename = "@weekPadding")] week_padding: Option, #[serde(rename = "@dayPadding")] @@ -2087,7 +2069,7 @@ struct Format { #[serde(default, rename = "relabel")] relabels: Vec, #[serde(default, rename = "affix")] - affixes: Vec, + _affixes: Vec, } impl Format { @@ -2125,231 +2107,6 @@ impl Format { } } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct NumberFormat { - #[serde(rename = "@maximumFractionDigits")] - maximum_fraction_digits: Option, - #[serde(rename = "@useGrouping")] - use_grouping: Option, - #[serde(rename = "@scientific")] - scientific: Option, - #[serde(default, rename = "@prefix")] - prefix: String, - #[serde(default, rename = "@suffix")] - suffix: String, - #[serde(default, rename = "affix")] - affixes: Vec, -} - -struct SignificantNumberFormat<'a> { - scientific: Option, - prefix: &'a str, - suffix: &'a str, - use_grouping: Option, - maximum_fraction_digits: Option, -} - -impl<'a> From<&'a NumberFormat> for SignificantNumberFormat<'a> { - fn from(value: &'a NumberFormat) -> Self { - Self { - scientific: value.scientific, - prefix: &value.prefix, - suffix: &value.suffix, - use_grouping: value.use_grouping, - maximum_fraction_digits: value.maximum_fraction_digits, - } - } -} - -impl<'a> From<&'a Format> for SignificantNumberFormat<'a> { - fn from(value: &'a Format) -> Self { - Self { - scientific: value.scientific, - prefix: &value.prefix, - suffix: &value.suffix, - use_grouping: value.use_grouping, - maximum_fraction_digits: value.maximum_fraction_digits, - } - } -} - -impl<'a> SignificantNumberFormat<'a> { - fn decode(&self) -> crate::format::Format { - let type_ = if self.scientific == Some(RawScientific::True) { - Type::E - } else if self.prefix == "$" { - Type::Dollar - } else if self.suffix == "%" { - Type::Pct - } else if self.use_grouping == Some(true) { - Type::Comma - } else { - Type::F - }; - let d = match self.maximum_fraction_digits { - Some(d) if (0..=15).contains(&d) => d, - _ => 2, - }; - UncheckedFormat { - type_, - w: 40, - d: d as u8, - } - .fix() - } -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct DateTimeFormat { - #[serde(rename = "@baseFormat")] - base_format: BaseFormat, - #[serde(rename = "@mdyOrder")] - mdy_order: Option, - #[serde(rename = "@showQuarter")] - show_quarter: Option, - #[serde(rename = "@yearAbbreviation")] - year_abbreviation: Option, - #[serde(rename = "@monthFormat")] - month_format: Option, - #[serde(rename = "@showWeek")] - show_week: Option, - #[serde(rename = "@showDay")] - show_day: Option, - #[serde(rename = "@showHour")] - show_hour: Option, - #[serde(rename = "@showSecond")] - show_second: Option, - #[serde(rename = "@showMillis")] - show_millis: Option, - #[serde(default, rename = "affix")] - affixes: Vec, -} - -struct SignificantDateTimeFormat { - base_format: Option, - show_quarter: Option, - show_week: Option, - show_day: Option, - show_hour: Option, - show_second: Option, - show_millis: Option, - mdy_order: Option, - month_format: Option, - year_abbreviation: Option, -} - -impl From<&Format> for SignificantDateTimeFormat { - fn from(value: &Format) -> Self { - Self { - base_format: value.base_format, - show_quarter: value.show_quarter, - show_week: value.show_week, - show_day: value.show_day, - show_hour: value.show_hour, - show_second: value.show_second, - show_millis: value.show_millis, - mdy_order: value.mdy_order, - month_format: value.month_format, - year_abbreviation: value.year_abbreviation, - } - } -} -impl From<&DateTimeFormat> for SignificantDateTimeFormat { - fn from(value: &DateTimeFormat) -> Self { - Self { - base_format: Some(value.base_format), - show_quarter: value.show_quarter, - show_week: value.show_week, - show_day: value.show_day, - show_hour: value.show_hour, - show_second: value.show_second, - show_millis: value.show_millis, - mdy_order: value.mdy_order, - month_format: value.month_format, - year_abbreviation: value.year_abbreviation, - } - } -} -impl SignificantDateTimeFormat { - fn decode(&self) -> crate::format::Format { - let type_ = match self.base_format { - Some(BaseFormat::Date) => { - let type_ = if self.show_quarter == Some(true) { - Type::QYr - } else if self.show_week == Some(true) { - Type::WkYr - } else { - match (self.mdy_order, self.month_format) { - (Some(MdyOrder::DayMonthYear), Some(MonthFormat::Number)) => Type::EDate, - (Some(MdyOrder::DayMonthYear), Some(MonthFormat::PaddedNumber)) => { - Type::EDate - } - (Some(MdyOrder::DayMonthYear), _) => Type::Date, - (Some(MdyOrder::YearMonthDay), _) => Type::SDate, - _ => Type::ADate, - } - }; - let mut w = type_.min_width(); - if self.year_abbreviation != Some(true) { - w += 2; - }; - return UncheckedFormat { type_, w, d: 0 }.try_into().unwrap(); - } - Some(BaseFormat::DateTime) => { - if self.mdy_order == Some(MdyOrder::YearMonthDay) { - Type::YmdHms - } else { - Type::DateTime - } - } - _ => { - if self.show_day == Some(true) { - Type::DTime - } else if self.show_hour == Some(true) { - Type::Time - } else { - Type::MTime - } - } - }; - date_time_format(type_, self.show_second, self.show_millis) - } -} - -fn date_time_format( - type_: Type, - show_second: Option, - show_millis: Option, -) -> crate::format::Format { - let mut w = type_.min_width(); - let mut d = 0; - if show_second == Some(true) { - w += 3; - if show_millis == Some(true) { - d = 3; - w += d as u16 + 1; - } - } - UncheckedFormat { type_, w, d }.try_into().unwrap() -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct ElapsedTimeFormat { - #[serde(rename = "@showDay")] - show_day: Option, - #[serde(rename = "@showHour")] - show_hour: Option, - #[serde(rename = "@showSecond")] - show_second: Option, - #[serde(rename = "@showMillis")] - show_millis: Option, - #[serde(default, rename = "affix")] - affixes: Vec, -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] enum BaseFormat { @@ -2464,7 +2221,7 @@ enum RawScientific { struct Affix { /// A reference to a footnote with the given 1-based index. #[serde(rename = "@definesReference")] - defines_reference: NonZeroUsize, + _defines_reference: NonZeroUsize, } #[derive(Deserialize, Debug)] @@ -2485,15 +2242,6 @@ impl Relabel { } } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct ValueMapEntry { - #[serde(rename = "@from")] - from: String, - #[serde(rename = "@to")] - to: String, -} - struct Element<'a> { raw: &'a RawElement, style: Cow<'a, Style>, @@ -2790,14 +2538,6 @@ impl Graph { .collect() } - fn x_dimension(&self) -> Option<&Dimension> { - self.axis_dimension(Axis3::X) - } - - fn y_dimension(&self) -> Option<&Dimension> { - self.axis_dimension(Axis3::Y) - } - fn axis_dimension(&self, axis: Axis3) -> Option<&Dimension> { self.coordinates.dimensions[axis].as_ref() } @@ -2934,15 +2674,15 @@ enum Graphic { #[derive(Debug)] struct RawElement { id: Option, - break_representation: Option, - closed: bool, - preserve_straight_lines: bool, - center_in_3d: bool, - median_style: Option, - fence_style: Option, - hinge_style: Option, - outlier_style: Option, - extreme_style: Option, + _break_representation: Option, + _closed: bool, + _preserve_straight_lines: bool, + _center_in_3d: bool, + _median_style: Option, + _fence_style: Option, + _hinge_style: Option, + _outlier_style: Option, + _extreme_style: Option, style: Option, statistics: Vec, @@ -3003,6 +2743,9 @@ impl<'de> Deserialize<'de> for RawElement { #[serde(rename = "@style")] style: Option, + #[serde(rename = "@clip")] + clip: Option, + #[serde(rename = "$value")] statistics: Vec, @@ -3022,15 +2765,15 @@ impl<'de> Deserialize<'de> for RawElement { } Ok(Self { id: raw.id, - break_representation: raw.break_representation, - closed: raw.closed, - preserve_straight_lines: raw.preserve_straight_lines, - center_in_3d: raw.center_in_3d, - median_style: raw.median_style, - fence_style: raw.fence_style, - hinge_style: raw.hinge_style, - outlier_style: raw.outlier_style, - extreme_style: raw.extreme_style, + _break_representation: raw.break_representation, + _closed: raw.closed, + _preserve_straight_lines: raw.preserve_straight_lines, + _center_in_3d: raw.center_in_3d, + _median_style: raw.median_style, + _fence_style: raw.fence_style, + _hinge_style: raw.hinge_style, + _outlier_style: raw.outlier_style, + _extreme_style: raw.extreme_style, style: raw.style, statistics: raw.statistics, positions, @@ -3045,40 +2788,40 @@ impl<'de> Deserialize<'de> for RawElement { #[serde(rename_all = "camelCase")] struct ColorAesthetic { #[serde(rename = "@id")] - id: Option, + _id: Option, #[serde(rename = "@domainModifier")] - domain_modifier: Option, + _domain_modifier: Option, #[serde(rename = "@variable")] variable: Option, #[serde(rename = "@dimension")] - dimension: Option, + _dimension: Option, #[serde(rename = "@domain")] - domain: Option, + _domain: Option, #[serde(rename = "@clamp")] - clamp: Option, + _clamp: Option, #[serde(default, rename = "@split")] - split: bool, + _split: bool, //summary_statistic: Option, - #[serde(default)] - color_mapping: Vec, + #[serde(default, rename = "colorMapping")] + _color_mapping: Vec, #[serde(rename = "@scale")] - scale: Option, + _scale: Option, #[serde(rename = "@affect")] affect: Option, #[serde(rename = "@cycle")] - cycle: Option, + _cycle: Option, #[serde(rename = "@missing")] - missing: Option, + _missing: Option, #[serde(rename = "@low")] - low: Option, + _low: Option, #[serde(rename = "@high")] - high: Option, + _high: Option, } #[derive(Deserialize, Debug)] @@ -3095,9 +2838,9 @@ struct StyleBy { #[serde(rename_all = "camelCase")] struct ColorMapping { #[serde(rename = "@from")] - from: String, + _from: String, #[serde(rename = "@to")] - to: String, + _to: String, } #[derive(Copy, Clone, Deserialize, Debug, PartialEq, Eq)] @@ -3174,7 +2917,7 @@ enum Location2 { }, SizeToContent { axis: Axis2, - min: Option, + _min: Option, max: Option, }, } @@ -3233,7 +2976,7 @@ impl Location { if self.component() == Component::Length { Some(Location2::SizeToContent { axis: self.axis(), - min: self.min, + _min: self.min, max: self.max, }) } else { @@ -3303,6 +3046,7 @@ impl Part { } } + #[allow(dead_code)] fn opposite(&self) -> Option { match self { Part::Left => Some(Part::Right), @@ -3317,10 +3061,36 @@ impl Part { #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct Faceting { + /// How to derive the domain for the facet cells. + #[serde(default, rename = "@method")] + _method: FacetingMethod, + + #[serde(default, rename = "@augmentEmptyCells")] + _augment_empty_cells: bool, + #[serde(default, rename = "$value")] children: Vec, } +/// How to derive the domain for facet axes. +#[derive(Copy, Clone, Deserialize, Debug, Default, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +enum FacetingMethod { + /// Produce a single domain for all of the facet cells by considering all of + /// their data together. + #[default] + Cross, + + /// Each facet cell has its own independent domain based only on its own + /// data. + /// + /// Each facet cell will have its own axis (see [Axis]). + Nest, + + /// Effect not known yet. + Dot, +} + #[derive(Clone, Debug)] struct Facet<'a> { series: &'a Series, @@ -3476,17 +3246,17 @@ impl Nest { #[serde(rename_all = "camelCase")] struct Layer { #[serde(rename = "@variable")] - variable: String, + _variable: String, #[serde(rename = "@value")] - value: String, + _value: String, } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct FacetLayout { #[serde(default, rename = "@topDown")] - top_down: bool, + _top_down: bool, #[serde(default, rename = "$value")] children: Vec, @@ -3501,7 +3271,7 @@ impl FacetLayout { #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] enum FacetLayoutChild { - SetCellProperties(SetCellProperties), + SetCellProperties(#[allow(dead_code)] SetCellProperties), FacetLevel(FacetLevel), #[serde(other)] Other, @@ -3520,33 +3290,33 @@ impl FacetLayoutChild { #[serde(rename_all = "camelCase")] struct SetCellProperties { #[serde(rename = "@applyToConverse", default)] - apply_to_converse: bool, + _apply_to_converse: bool, #[serde(rename = "$value")] - sets: Vec, + _sets: Vec, #[serde(rename = "union")] - union_: Option, + _union: Option, } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct Union { #[serde(default, rename = "intersect")] - intersects: Vec, + _intersects: Vec, } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct Intersect { #[serde(default, rename = "$value")] - children: Vec, + _children: Vec, } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] enum IntersectChild { - Where(Where), + Where(#[allow(dead_code)] Where), #[serde(other)] Other, } @@ -3555,16 +3325,16 @@ enum IntersectChild { #[serde(rename_all = "camelCase")] struct Where { #[serde(rename = "@variable")] - variable: String, + _variable: String, #[serde(rename = "@include")] - include: String, + _include: String, } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] enum Set { - SetStyle(SetStyle), - SetFrameStyle(SetFrameStyle), + SetStyle(#[allow(dead_code)] SetStyle), + SetFrameStyle(#[allow(dead_code)] SetFrameStyle), #[serde(other)] Other, } @@ -3573,22 +3343,22 @@ enum Set { #[serde(rename_all = "camelCase")] struct SetStyle { #[serde(rename = "@target")] - target: String, + _target: String, /// The `id` for a [Style]. #[serde(rename = "@style")] - style: String, + _style: String, } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct SetFrameStyle { #[serde(rename = "@target")] - target: String, + _target: String, /// The `id` for a [Style]. #[serde(rename = "@style")] - style: String, + _style: String, } #[derive(Debug)] @@ -3632,11 +3402,11 @@ impl<'de> Deserialize<'de> for Coordinates { #[serde(rename_all = "camelCase")] struct Dimension { #[serde(default, rename = "@unionDomain")] - union_domain: bool, + _union_domain: bool, /// A reference to an [IntervalDomain] or [CategoricalDomain]. #[serde(default, rename = "@domain")] - domain: Option, + _domain: Option, #[serde(rename = "@upperMargin")] upper_margin: Option, @@ -3645,15 +3415,16 @@ struct Dimension { lower_margin: Option, #[serde(default, rename = "@niceUpperMapping")] - nice_upper_mapping: bool, + _nice_upper_mapping: bool, #[serde(default, rename = "@niceLowerMapping")] - nice_lower_mapping: bool, + _nice_lower_mapping: bool, #[serde(default, rename = "@facetsShareScale")] - facets_share_scale: bool, + _facets_share_scale: bool, - scale: Option, + #[serde(rename = "scale")] + _scale: Option, /// Maximum 2 axes. /// @@ -3667,7 +3438,7 @@ struct Dimension { #[serde(rename_all = "camelCase")] struct Scale { #[serde(rename = "@method")] - method: Method, + _method: Method, } #[derive(Copy, Clone, Deserialize, Debug, PartialEq, Eq)] @@ -3702,7 +3473,7 @@ enum Clip { enum Statistic { BinStatistic(BinStatistic), SummaryStatistic(SummaryStatistic), - DistributionStatistic(DistributionStatistic), + DistributionStatistic(#[allow(dead_code)] DistributionStatistic), TukeyStatistic, #[serde(other)] Other, @@ -3927,72 +3698,12 @@ enum Distribution { #[serde(rename_all = "camelCase")] struct Coordinate { #[serde(rename = "@id")] - id: Option, + _id: Option, #[serde(rename = "@variable")] variable: String, } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct Labeling { - #[serde(default, rename = "@connectingLines")] - connecting_lines: bool, - - /// The `id` for a [Style]. - #[serde(rename = "@style")] - style: Option, - - /// The `id` for a [Style]. - #[serde(rename = "@textFrameStyle")] - text_frame_style: Option, - - #[serde(rename = "$value", default)] - children: Vec, -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -enum LabelingChild { - Formatting(Formatting), - Footnotes(Footnotes), - #[serde(other)] - Other, -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct Formatting { - #[serde(rename = "@variable")] - variable: String, -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct Footnotes { - #[serde(rename = "@variable")] - variable: String, - - #[serde(default, rename = "@superscript")] - superscript: bool, - - #[serde(default, rename = "footnoteMapping")] - mappings: Vec, -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct FootnoteMapping { - #[serde(rename = "@definesReference")] - defines_reference: Option, - - #[serde(rename = "@from")] - from: NonZeroUsize, - - #[serde(rename = "@to")] - to: String, -} - #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct FacetLevel { @@ -4002,6 +3713,32 @@ struct FacetLevel { axis: Axis, } +/// Controls the display of the axis for a dimension. +/// +/// An axis consists of: +/// +/// - Tick marks, if `major_ticks` and optionally `minor_ticks` are set. +/// +/// - A label, if `label` is set. +/// +/// # Faceted axes +/// +/// In a faceted graph, the axis is shown either once or in every cell, +/// according to the rules below, in order of decreasing priority: +/// +/// - If the dimension has a polar transform, then the axis is drawn in every +/// cell (because there's no reasonable way to draw it just once). +/// +/// - With [AxisRepeat::Never], then the axis is drawn just once. (This can +/// produce deceptive results with [FacetingMethod::Nest], since in that case +/// different facet cells might have different axes.) +/// +/// - With [FacetingMethod::Nest] then the axis is drawn in every cell because +/// each cell has a different axis. +/// +/// - With [AxisRepeat::Always], the axis is drawn in every cell. +/// +/// - Otherwise, the axis is drawn just once. #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct Axis { @@ -4014,14 +3751,47 @@ struct Axis { #[serde(rename = "@opposite", default)] opposite: bool, - /// If false, `label` appears once per facet along the axis. + /// When faceting is present, this influences whether the axis appears a + /// single time or separately for each facet cell. + /// + /// This is ignored if the axis has a polar transformation. + #[serde(rename = "@repeat")] + _repeat: Option, + + /// When axes are repeated in each facet cell (as influenced by `repeat`), + /// this determines whether `label` appears once or in each facet cell: /// - /// If true, `label` appears once along the axis. + /// - If false, `label` appears once per facet cell. + /// + /// - If true, `label` appears just once. + /// + /// When axes appear just once, the axis label also appears only once + /// regardless of this setting. #[serde(rename = "@combineAxisLabels", default)] combine_axis_labels: bool, - label: Option