]> pintos-os.org Git - pspp/commitdiff
cleanup
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 25 Aug 2026 17:35:26 +0000 (10:35 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 25 Aug 2026 17:35:26 +0000 (10:35 -0700)
12 files changed:
rust/doc/src/spv/graphs.md
rust/pspp/src/spv/read.rs
rust/pspp/src/spv/read/graph.rs
rust/pspp/src/spv/read/graph/format.rs
rust/pspp/src/spv/read/graph/frames.rs
rust/pspp/src/spv/read/graph/patterns.rs
rust/pspp/src/spv/read/graph/style.rs
rust/pspp/src/spv/read/graph/symbols.rs
rust/pspp/src/spv/read/light.rs
rust/pspp/src/spv/read/structure.rs
rust/pspp/src/spv/testdata/.gitignore [new file with mode: 0644]
rust/pspp/src/spv/testdata/graph4.xml

index 0013e94147a77782bf2de0385785381dfeb742d8..dcb2580155196abe8c404b401ab63bd328e30eb2 100644 (file)
@@ -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.
 
index 01186a64a5d0be13e83ca22caa15a5afd881af10..1434a9f7c0730fd8b8779bd91c3d17e3848f3fc6 100644 (file)
@@ -13,7 +13,6 @@
 //
 // You should have received a copy of the GNU General Public License along with
 // this program.  If not, see <http://www.gnu.org/licenses/>.
-#![allow(dead_code)]
 use std::{
     fmt::Display,
     fs::File,
index 004b9471797fae9f83e75e3f375497eedcf595c1..dbdea52f6e69ad8235e2c00bce15f3ec936c8d26 100644 (file)
@@ -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<String>,
-    short_label: Option<String>,
-    weight: bool,
-    key: bool,
+    _label: Option<String>,
+    _short_label: Option<String>,
+    _weight: bool,
+    _key: bool,
     categorical: bool,
     values: Vec<SeriesValue>,
     unique_values: Vec<SeriesValue>,
@@ -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<String>) -> 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<String>,
+    pub _file_name: Option<String>,
 
     #[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<StringFormat>,
 }
 
-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<String>) -> Option<usize> {
-        match self {
-            Domain::Categorical { values } => values.get_index_of(value),
-            _ => None,
-        }
-    }
     fn lookup(&self, value: &Datum<String>) -> Option<f64> {
         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<CategoricalDomainChild>,
@@ -1841,7 +1823,7 @@ struct IntervalDomain {
     id: String,
 
     #[serde(default, rename = "@date")]
-    date: bool,
+    _date: bool,
 
     #[serde(default, rename = "$value")]
     children: Vec<IntervalDomainChild>,
@@ -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<Relabel>,
     #[serde(default, rename = "affix")]
-    affixes: Vec<Affix>,
+    _affixes: Vec<Affix>,
 }
 
 impl StringFormat {
@@ -1986,9 +1968,9 @@ impl StringFormat {
 #[serde(rename_all = "camelCase")]
 struct Format {
     #[serde(rename = "@tryStringsAsNumbers")]
-    try_strings_as_numbers: Option<bool>,
+    _try_strings_as_numbers: Option<bool>,
     #[serde(rename = "@relabelsArePreformatted")]
-    relabels_are_preformatted: Option<bool>,
+    _relabels_are_preformatted: Option<bool>,
     #[serde(rename = "@separatorChars")]
     separator_chars: Option<String>,
     #[serde(rename = "@hiddenseparator")]
@@ -2031,7 +2013,7 @@ struct Format {
     #[serde(rename = "@mdyOrder")]
     mdy_order: Option<MdyOrder>,
     #[serde(rename = "@dayOfMonthPadding")]
-    day_of_month_padding: Option<bool>,
+    _day_of_month_padding: Option<bool>,
     #[serde(rename = "@weekPadding")]
     week_padding: Option<bool>,
     #[serde(rename = "@dayPadding")]
@@ -2087,7 +2069,7 @@ struct Format {
     #[serde(default, rename = "relabel")]
     relabels: Vec<Relabel>,
     #[serde(default, rename = "affix")]
-    affixes: Vec<Affix>,
+    _affixes: Vec<Affix>,
 }
 
 impl Format {
@@ -2125,231 +2107,6 @@ impl Format {
     }
 }
 
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase")]
-struct NumberFormat {
-    #[serde(rename = "@maximumFractionDigits")]
-    maximum_fraction_digits: Option<usize>,
-    #[serde(rename = "@useGrouping")]
-    use_grouping: Option<bool>,
-    #[serde(rename = "@scientific")]
-    scientific: Option<RawScientific>,
-    #[serde(default, rename = "@prefix")]
-    prefix: String,
-    #[serde(default, rename = "@suffix")]
-    suffix: String,
-    #[serde(default, rename = "affix")]
-    affixes: Vec<Affix>,
-}
-
-struct SignificantNumberFormat<'a> {
-    scientific: Option<RawScientific>,
-    prefix: &'a str,
-    suffix: &'a str,
-    use_grouping: Option<bool>,
-    maximum_fraction_digits: Option<usize>,
-}
-
-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<MdyOrder>,
-    #[serde(rename = "@showQuarter")]
-    show_quarter: Option<bool>,
-    #[serde(rename = "@yearAbbreviation")]
-    year_abbreviation: Option<bool>,
-    #[serde(rename = "@monthFormat")]
-    month_format: Option<MonthFormat>,
-    #[serde(rename = "@showWeek")]
-    show_week: Option<bool>,
-    #[serde(rename = "@showDay")]
-    show_day: Option<bool>,
-    #[serde(rename = "@showHour")]
-    show_hour: Option<bool>,
-    #[serde(rename = "@showSecond")]
-    show_second: Option<bool>,
-    #[serde(rename = "@showMillis")]
-    show_millis: Option<bool>,
-    #[serde(default, rename = "affix")]
-    affixes: Vec<Affix>,
-}
-
-struct SignificantDateTimeFormat {
-    base_format: Option<BaseFormat>,
-    show_quarter: Option<bool>,
-    show_week: Option<bool>,
-    show_day: Option<bool>,
-    show_hour: Option<bool>,
-    show_second: Option<bool>,
-    show_millis: Option<bool>,
-    mdy_order: Option<MdyOrder>,
-    month_format: Option<MonthFormat>,
-    year_abbreviation: Option<bool>,
-}
-
-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<bool>,
-    show_millis: Option<bool>,
-) -> 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<bool>,
-    #[serde(rename = "@showHour")]
-    show_hour: Option<bool>,
-    #[serde(rename = "@showSecond")]
-    show_second: Option<bool>,
-    #[serde(rename = "@showMillis")]
-    show_millis: Option<bool>,
-    #[serde(default, rename = "affix")]
-    affixes: Vec<Affix>,
-}
-
 #[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<String>,
-    break_representation: Option<BreakRepresentation>,
-    closed: bool,
-    preserve_straight_lines: bool,
-    center_in_3d: bool,
-    median_style: Option<String>,
-    fence_style: Option<String>,
-    hinge_style: Option<String>,
-    outlier_style: Option<String>,
-    extreme_style: Option<String>,
+    _break_representation: Option<BreakRepresentation>,
+    _closed: bool,
+    _preserve_straight_lines: bool,
+    _center_in_3d: bool,
+    _median_style: Option<String>,
+    _fence_style: Option<String>,
+    _hinge_style: Option<String>,
+    _outlier_style: Option<String>,
+    _extreme_style: Option<String>,
     style: Option<String>,
     statistics: Vec<Statistic>,
 
@@ -3003,6 +2743,9 @@ impl<'de> Deserialize<'de> for RawElement {
             #[serde(rename = "@style")]
             style: Option<String>,
 
+            #[serde(rename = "@clip")]
+            clip: Option<Clip>,
+
             #[serde(rename = "$value")]
             statistics: Vec<Statistic>,
 
@@ -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<String>,
+    _id: Option<String>,
     #[serde(rename = "@domainModifier")]
-    domain_modifier: Option<String>,
+    _domain_modifier: Option<String>,
     #[serde(rename = "@variable")]
     variable: Option<String>,
     #[serde(rename = "@dimension")]
-    dimension: Option<usize>,
+    _dimension: Option<usize>,
     #[serde(rename = "@domain")]
-    domain: Option<String>,
+    _domain: Option<String>,
     #[serde(rename = "@clamp")]
-    clamp: Option<bool>,
+    _clamp: Option<bool>,
     #[serde(default, rename = "@split")]
-    split: bool,
+    _split: bool,
     //summary_statistic: Option<SummaryStatistic>,
-    #[serde(default)]
-    color_mapping: Vec<ColorMapping>,
+    #[serde(default, rename = "colorMapping")]
+    _color_mapping: Vec<ColorMapping>,
 
     #[serde(rename = "@scale")]
-    scale: Option<ColorScale>,
+    _scale: Option<ColorScale>,
 
     #[serde(rename = "@affect")]
     affect: Option<ColorAffect>,
 
     #[serde(rename = "@cycle")]
-    cycle: Option<String>,
+    _cycle: Option<String>,
 
     #[serde(rename = "@missing")]
-    missing: Option<String>,
+    _missing: Option<String>,
 
     #[serde(rename = "@low")]
-    low: Option<String>,
+    _low: Option<String>,
 
     #[serde(rename = "@high")]
-    high: Option<String>,
+    _high: Option<String>,
 }
 
 #[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<LocationLength>,
+        _min: Option<LocationLength>,
         max: Option<LocationLength>,
     },
 }
@@ -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<Self> {
         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<FacetingChild>,
 }
 
+/// 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<FacetLayoutChild>,
@@ -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<Set>,
+    _sets: Vec<Set>,
 
     #[serde(rename = "union")]
-    union_: Option<Union>,
+    _union: Option<Union>,
 }
 
 #[derive(Deserialize, Debug)]
 #[serde(rename_all = "camelCase")]
 struct Union {
     #[serde(default, rename = "intersect")]
-    intersects: Vec<Intersect>,
+    _intersects: Vec<Intersect>,
 }
 
 #[derive(Deserialize, Debug)]
 #[serde(rename_all = "camelCase")]
 struct Intersect {
     #[serde(default, rename = "$value")]
-    children: Vec<IntersectChild>,
+    _children: Vec<IntersectChild>,
 }
 
 #[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<String>,
+    _domain: Option<String>,
 
     #[serde(rename = "@upperMargin")]
     upper_margin: Option<LocationLength>,
@@ -3645,15 +3415,16 @@ struct Dimension {
     lower_margin: Option<LocationLength>,
 
     #[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<Scale>,
+    #[serde(rename = "scale")]
+    _scale: Option<Scale>,
 
     /// 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<String>,
+    _id: Option<String>,
 
     #[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<String>,
-
-    /// The `id` for a [Style].
-    #[serde(rename = "@textFrameStyle")]
-    text_frame_style: Option<String>,
-
-    #[serde(rename = "$value", default)]
-    children: Vec<LabelingChild>,
-}
-
-#[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<FootnoteMapping>,
-}
-
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase")]
-struct FootnoteMapping {
-    #[serde(rename = "@definesReference")]
-    defines_reference: Option<NonZeroUsize>,
-
-    #[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<AxisRepeat>,
+
+    /// 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<Label>,
+    /// If set, enables showing tick marks and labels along the axis.  If
+    /// `None`, the axis consists only of `label` (if any).
     major_ticks: Option<MajorTicks>,
+
+    /// Label for the axis.
+    label: Option<Label>,
+}
+
+/// Whether an axis should appear a single time or separately for each facet
+/// cell.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Enum)]
+#[serde(rename_all = "camelCase")]
+enum AxisRepeat {
+    /// Repeat the axis in every facet cell.
+    Always,
+
+    /// Draw the axis only in one place.
+    ///
+    /// This can produce deceptive results if `faceting` specifies
+    /// `method="nest"`, since in that case different facet cells might have
+    /// different axes.
+    Never,
 }
 
 #[derive(Deserialize, Debug)]
@@ -4029,7 +3799,7 @@ struct Axis {
 struct MajorTicks {
     /// The `id` for a [Style].
     #[serde(rename = "@style")]
-    style: String,
+    _style: String,
 }
 
 #[derive(Deserialize, Debug)]
@@ -4041,10 +3811,10 @@ struct Label {
 
     /// The `id` for a [Style].
     #[serde(rename = "@textFrameStyle")]
-    text_frame_style: Option<String>,
+    _text_frame_style: Option<String>,
 
     #[serde(rename = "@purpose")]
-    purpose: Option<Purpose>,
+    _purpose: Option<Purpose>,
 
     #[serde(rename = "$value")]
     child: LabelChild,
@@ -4086,44 +3856,16 @@ struct Text {
     /// If this is present, then `text` defines the content or the marker for a
     /// footnote.
     #[serde(rename = "@usesReference")]
-    uses_reference: Option<NonZeroUsize>,
+    _uses_reference: Option<NonZeroUsize>,
 
     /// If this is present, then
     #[serde(rename = "@definesReference")]
-    defines_reference: Option<NonZeroUsize>,
+    _defines_reference: Option<NonZeroUsize>,
 
     #[serde(default, rename = "$text")]
     text: String,
 }
 
-enum DecodedText<'a> {
-    /// Defines footnote `index` content or marker as `text`.
-    FootnoteDefinition { index: usize, text: &'a str },
-
-    /// Adds a reference to footnote `index`.
-    FootnoteReference { index: usize },
-
-    /// Text content.
-    Text { text: &'a str },
-}
-
-impl Text {
-    fn decode(&self) -> DecodedText<'_> {
-        if let Some(uses_reference) = self.uses_reference {
-            DecodedText::FootnoteDefinition {
-                index: uses_reference.get() - 1,
-                text: &self.text,
-            }
-        } else if let Some(defines_reference) = self.defines_reference {
-            DecodedText::FootnoteReference {
-                index: defines_reference.get() - 1,
-            }
-        } else {
-            DecodedText::Text { text: &self.text }
-        }
-    }
-}
-
 #[derive(Deserialize, Debug)]
 #[serde(rename_all = "camelCase")]
 struct LabelFrame {
@@ -4176,15 +3918,6 @@ impl<'de> Deserialize<'de> for Container {
             LabelFrame(LabelFrame),
         }
 
-        impl ContainerChild {
-            fn location(&self) -> Option<&Location> {
-                match self {
-                    Self::Location(location) => Some(location),
-                    _ => None,
-                }
-            }
-        }
-
         let raw_container = RawContainer::deserialize(deserializer)?;
         let mut locations = Vec::new();
         let mut children = Vec::new();
@@ -4272,6 +4005,7 @@ impl LocationLength {
         }
     }
 
+    #[allow(dead_code)]
     fn as_percent(&self) -> Option<f64> {
         match *self {
             LocationLength::Absolute(_) => None,
@@ -4345,6 +4079,7 @@ impl<'a> Frame<'a> {
             .map(|position| position.missing_values())
             .sum()
     }
+    #[allow(dead_code)]
     fn demerits(&self, frames: &Frames) -> f64 {
         let error_demerits = self.position.values().map(|p| p.demerits()).sum::<f64>();
         let preferred = frames.preferred_size(self, false);
@@ -4410,6 +4145,7 @@ impl Rect {
             .sum()
     }
 
+    #[allow(dead_code)]
     fn as_svg(&self) -> Rectangle {
         Rectangle::new()
             .set("x", self.0[Axis2::X].0)
@@ -4541,10 +4277,12 @@ impl Scaling {
         (0..self.n_ticks).map(|i| self.base + self.interval * (i as f64))
     }
 
+    #[allow(dead_code)]
     pub fn first(&self) -> Option<f64> {
         self.ticks().next()
     }
 
+    #[allow(dead_code)]
     pub fn last(&self) -> Option<f64> {
         self.ticks().next_back()
     }
@@ -4599,13 +4337,6 @@ impl Scaling {
             // and so on.
             let basic_interval = f64::powi(10.0, r.log10().floor() as i32 - 1);
 
-            struct Candidate {
-                /// The scaling candidate.
-                scaling: Scaling,
-                /// Lower scores are better.
-                score: f64,
-            }
-
             // Find the most pleasing interval.
             [1.0, 2.0, 5.0, 10.0]
                 .into_iter()
@@ -4719,12 +4450,14 @@ fn sturges_rule(n: f64) -> Option<usize> {
 
 /// Returns the number of bins suggested by an approximation to Doane's rule,
 /// for `n` observations.
+#[allow(dead_code)]
 fn doane_rule(n: f64) -> Option<usize> {
     NumCast::from((3.0 + n.log10() * n.log2()).ceil())
 }
 
 /// Returns the number of bins suggested by the Freedman-Diaconis rule for `n`
 /// observations with an interquartile range of `iqr`.
+#[allow(dead_code)]
 fn diaconis_rule(iqr: f64, n: f64) -> Option<usize> {
     NumCast::from((2.0 * iqr / n.cbrt()).ceil())
 }
@@ -4815,14 +4548,6 @@ struct FacetHeadings<'a> {
 
     /// Number of facets.
     n_facets: usize,
-
-    /// [AxisDomain] for X or Y axis.
-    ///
-    /// Currently there's always exactly one of these for an axis, although
-    /// perhaps there should be up to 2.
-    axis_domain: &'a AxisDomain<'a>,
-
-    rotate_ticks: bool,
 }
 
 struct FacetAxisHeight<'a> {
@@ -4966,11 +4691,9 @@ impl<'a> FacetHeadings<'a> {
         Self {
             width,
             axes,
-            axis_domain,
             ticks,
             facets,
             n_facets,
-            rotate_ticks,
         }
     }
 
index 3e5113dae2e6c68baf2d24f664a5294ceb812010..9de78134816455a2fd200899bbf3ea1c56211d03 100644 (file)
@@ -14,9 +14,7 @@ use crate::{
     data::Datum,
     format::group_digits,
     locale::{DayLength, HourCount, Item, Locale, MonthLength, PatternType, data::EN},
-    spv::read::graph::{
-        BaseFormat, DayType, Format, HourFormat, Mdy, MdyOrder, MonthFormat, RawScientific,
-    },
+    spv::read::graph::{DayType, Format, HourFormat, Mdy, MonthFormat, RawScientific},
     util::ToSmallString as _,
 };
 
@@ -96,7 +94,7 @@ enum NumberExpression {
 
 #[derive(Clone, Debug)]
 pub struct NumberFormatter {
-    pub locale: &'static Locale<'static>,
+    pub _locale: &'static Locale<'static>,
 
     pub minimum_fraction_digits: Option<usize>,
     pub maximum_fraction_digits: Option<usize>,
@@ -188,7 +186,7 @@ impl Default for NumberFormatter {
 }
 
 impl NumberFormatter {
-    pub fn default_for_locale(locale: &'static Locale<'static>) -> Self {
+    pub fn default_for_locale(_locale: &'static Locale<'static>) -> Self {
         Self {
             minimum_fraction_digits: None,
             maximum_fraction_digits: None,
@@ -198,16 +196,16 @@ impl NumberFormatter {
             negative_location: NegativeLocation::default(),
             scaling_factor: 1.0,
             scientific: Scientific::Auto,
-            decimal: locale.decimal(),
-            group: Some(locale.group()),
+            decimal: _locale.decimal(),
+            group: Some(_locale.group()),
             error: '*',
             prefix: String::new(),
             suffix: String::new(),
-            locale,
+            _locale,
         }
     }
 
-    pub fn new(format: &Format, locale: &'static Locale<'static>) -> Self {
+    pub fn new(format: &Format, _locale: &'static Locale<'static>) -> Self {
         Self {
             maximum_fraction_digits: format.maximum_fraction_digits,
             minimum_fraction_digits: format.minimum_fraction_digits,
@@ -241,21 +239,23 @@ impl NumberFormatter {
                 Some(RawScientific::WhenNeeded) => Scientific::WhenNeeded,
                 None => Scientific::Auto,
             },
-            decimal: format.decimal(locale),
+            decimal: format.decimal(_locale),
             group: format
                 .use_grouping
                 .unwrap_or(true)
-                .then(|| format.group(locale)),
+                .then(|| format.group(_locale)),
             error: format.error_character.unwrap_or('*'),
             prefix: format.prefix.clone(),
             suffix: format.suffix.clone(),
-            locale,
+            _locale,
         }
     }
 
+    #[allow(dead_code)]
     pub fn with_scientific(self, scientific: Scientific) -> Self {
         Self { scientific, ..self }
     }
+    #[allow(dead_code)]
     pub fn with_minimum_fraction_digits(self, minimum_fraction_digits: Option<usize>) -> Self {
         Self {
             minimum_fraction_digits,
@@ -268,33 +268,39 @@ impl NumberFormatter {
             ..self
         }
     }
+    #[allow(dead_code)]
     pub fn with_minimum_integer_digits(self, minimum_integer_digits: Option<usize>) -> Self {
         Self {
             minimum_integer_digits,
             ..self
         }
     }
+    #[allow(dead_code)]
     pub fn with_maximum_integer_digits(self, maximum_integer_digits: Option<usize>) -> Self {
         Self {
             maximum_integer_digits,
             ..self
         }
     }
+    #[allow(dead_code)]
     pub fn with_negatives(self, negatives: Negatives) -> Self {
         Self { negatives, ..self }
     }
+    #[allow(dead_code)]
     pub fn with_negative_location(self, negative_location: NegativeLocation) -> Self {
         Self {
             negative_location,
             ..self
         }
     }
+    #[allow(dead_code)]
     pub fn with_prefix(self, prefix: impl Into<String>) -> Self {
         Self {
             prefix: prefix.into(),
             ..self
         }
     }
+    #[allow(dead_code)]
     pub fn with_suffix(self, suffix: impl Into<String>) -> Self {
         Self {
             suffix: suffix.into(),
@@ -302,6 +308,7 @@ impl NumberFormatter {
         }
     }
 
+    #[allow(dead_code)]
     pub fn display<'a>(&'a self, value: &'a Datum<String>) -> impl Display {
         DisplayNumberFormatter {
             format: self,
@@ -389,6 +396,8 @@ impl NumberFormatter {
             None => f.write_str(&self.suffix),
         }
     }
+
+    #[allow(dead_code)]
     fn format_affixes(&self, body: &str, is_negative: bool) -> String {
         let mut prefixes: SmallVec<[&str; 2]> = smallvec![self.prefix.as_str()];
         let mut suffixes: SmallVec<[&str; 2]> = smallvec![self.suffix.as_str()];
@@ -668,90 +677,6 @@ impl DateFormatter {
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct DataFormat {
-    /// If this is set, then the number will be shown as the given type of date
-    /// or time format; otherwise it will be shown as just a number.
-    base_format: Option<BaseFormat>,
-
-    minimum_fraction_digits: Option<usize>,
-    maximum_fraction_digits: usize,
-    minimum_integer_digits: usize,
-    maximum_integer_digits: Option<usize>,
-    negatives: Negatives,
-    negative_location: NegativeLocation,
-
-    /// A number to divide the value by before formatting.
-    ///
-    /// # Examples
-    ///
-    /// - `scaling_factor` of 1000 with a `suffix` of `thousands`.
-    ///
-    /// - `scaling_factor` of 1e-6 with a `suffix` of `μ`.
-    scaling_factor: f64,
-
-    /// When to use scientific notation.
-    scientific: Scientific,
-
-    /// If true, then the formatter will try to parse strings as numbers, so
-    /// that numeric formatting rules (such as decimal points and grouping) can
-    /// be applied to them.
-    try_strings_as_numbers: bool,
-
-    /// Decimal point (commonly `.` or `,`).
-    decimal: char,
-    /// Grouping character (commonly `,` or `.`), only if grouping is enabled.
-    group: Option<char>,
-    /// Date separator (commonly `-`).
-    date: char,
-    /// Time separator (commonly `:`).
-    time: char,
-    /// For indicating errors (commonly `*`).
-    error: char,
-    /// Prefix (such as `$`).
-    prefix: String,
-    /// Suffix (such as `%`).
-    suffix: String,
-
-    mdy_order: MdyOrder,
-
-    show_era: bool,
-
-    show_year: bool,
-    year_abbreviation: bool,
-
-    show_quarter: bool,
-    quarter_prefix: String,
-    quarter_suffix: String,
-
-    show_month: bool,
-    month_format: MonthFormat,
-
-    show_week: bool,
-    week_padding: bool,
-    week_suffix: String,
-
-    show_wday: bool,
-    wday_padding: bool,
-    wday_abbreviation: bool,
-
-    show_day: bool,
-    day_padding: bool,
-    day_type: DayType,
-
-    show_hour: bool,
-    hour_padding: bool,
-    hour_format: HourFormat,
-
-    show_minute: bool,
-    minute_padding: bool,
-
-    second_padding: bool,
-    show_second: bool,
-
-    show_millis: bool,
-}
-
 #[derive(Debug)]
 struct ParsedNumber {
     s: SmallString<[u8; 32]>,
index cf7600a24a3c0d1db3c42325f107eb33a0637b34..6b29a1b7bd491e0c71da87ff4a58ccf5a9ce6b0e 100644 (file)
@@ -602,9 +602,6 @@ pub struct Position {
 }
 
 impl Position {
-    fn new() -> Self {
-        Self::default()
-    }
     pub fn start(&self) -> Option<f64> {
         self.values[Component::Start]
     }
@@ -659,17 +656,6 @@ impl Position {
         }
     }
 
-    fn case(&self) -> Case {
-        match (self.start(), self.end(), self.length()) {
-            (Some(start), Some(end), Some(length)) => Case::All { start, end, length },
-            (Some(start), None, None) => Case::Start(start),
-            (None, Some(end), None) => Case::End(end),
-            (None, None, Some(length)) => Case::Length(length),
-            (None, None, None) => Case::None,
-            _ => unreachable!(),
-        }
-    }
-
     fn assign_default_position(
         &mut self,
         frames: &[Frame],
@@ -769,14 +755,6 @@ impl Component {
     }
 }
 
-enum Case {
-    All { start: f64, end: f64, length: f64 },
-    Start(f64),
-    End(f64),
-    Length(f64),
-    None,
-}
-
 mod simplex {
     use std::{
         f64::consts::SQRT_2,
@@ -911,26 +889,12 @@ mod simplex {
     pub struct Point(pub [f64; 2]);
 
     impl Point {
-        pub fn new(x: f64, y: f64) -> Self {
-            Self([x, y])
-        }
-
-        pub fn into_parts(self) -> (f64, f64) {
-            (self.0[0], self.0[1])
-        }
-
         pub fn midpoint(self, other: Self) -> Self {
             Self([
                 self.0[0].midpoint(other.0[0]),
                 self.0[1].midpoint(other.0[1]),
             ])
         }
-
-        pub fn distance(self, other: Self) -> f64 {
-            let dx = self.0[0] - other.0[0];
-            let dy = self.0[1] - other.0[1];
-            dx.hypot(dy)
-        }
     }
 
     impl Mul<f64> for Point {
index 7c66006b8d30f311f249bad5b599291874f92a01..3574557e7b7118fc7436a497f343d70d36bbb180 100644 (file)
@@ -17,9 +17,6 @@ pub struct Pattern {
 }
 
 impl Pattern {
-    /// The number of patterns.
-    pub const N: usize = data::PATTERNS.len();
-
     /// Returns the pattern with the given `index`, or `None` if the index is
     /// greater than or equal to [Pattern::N].
     pub fn for_index(index: usize) -> Option<&'static Self> {
index 50a0a17e705a75025d8214b8a105379ea3bbb5a2..e9cb6399398b8ee037643d8b8381c806c942e0bd 100644 (file)
@@ -22,6 +22,7 @@ pub struct StyleCycle {
 }
 
 impl StyleCycle {
+    #[allow(dead_code)]
     pub fn get_style(&self, index: usize) -> Style {
         let mut iter = self.get_style_components(index);
         let style = iter.next().cloned().unwrap_or_default();
index 812c62024a6d90ca3da06d5ff1071537ec77bde6..d6025ef1b06064d34e1b0b0f5ed4672a644c734a 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(dead_code)]
 use std::f64::consts::PI;
 use std::fmt::Write as _;
 
index a6bff0ecb4aadf538fe14dfd689c501ca3ed807b..849123520e80a8db218443a3a0ffdb4084027458 100644 (file)
@@ -390,7 +390,7 @@ enum Version {
 #[derive(Debug)]
 struct Titles {
     #[br(args(context))]
-    title: Value,
+    _title: Value,
     #[br(temp)]
     _1: Optional<One>,
     #[br(args(context))]
@@ -803,9 +803,9 @@ struct Sizing {
     #[br(parse_with(parse_vec))]
     column_keeps: Vec<(i32, i32)>,
     #[br(parse_with(parse_vec))]
-    row_point_keeps: Vec<[i32; 3]>,
+    _row_point_keeps: Vec<[i32; 3]>,
     #[br(parse_with(parse_vec))]
-    column_point_keeps: Vec<[i32; 3]>,
+    _column_point_keeps: Vec<[i32; 3]>,
 }
 
 impl Sizing {
@@ -973,7 +973,7 @@ struct Formats {
     #[br(parse_with(parse_vec))]
     column_widths: Vec<i32>,
     locale: U32String,
-    current_layer: i32,
+    _current_layer: i32,
     #[br(temp, parse_with(parse_bool))]
     _x7: bool,
     #[br(temp, parse_with(parse_bool))]
@@ -1089,8 +1089,8 @@ struct Y1 {
 #[br(little)]
 #[derive(Debug)]
 struct Y2 {
-    custom_currency: CustomCurrency,
-    missing: u8,
+    _custom_currency: CustomCurrency,
+    _missing: u8,
     #[br(temp, parse_with(parse_bool))]
     _x17: bool,
 }
@@ -1149,11 +1149,11 @@ struct N2 {
     #[br(parse_with(parse_vec))]
     row_heights: Vec<i32>,
     #[br(parse_with(parse_vec))]
-    style_map: Vec<(i64, i16)>,
+    _style_map: Vec<(i64, i16)>,
     #[br(parse_with(parse_vec))]
-    styles: Vec<StylePair>,
+    _styles: Vec<StylePair>,
     #[br(parse_with(parse_counted))]
-    tail: Optional<[u8; 8]>,
+    _tail: Optional<[u8; 8]>,
 }
 
 #[binread]
@@ -1168,7 +1168,7 @@ struct N3 {
     #[br(magic = 1u8, temp)]
     _one: (),
     inner: Optional<N3Inner>,
-    y2: Y2,
+    _y2: Y2,
     #[br(temp)]
     _tail: Optional<N3Tail>,
 }
@@ -1651,7 +1651,7 @@ struct ValueMods {
     #[br(parse_with(parse_vec))]
     subscripts: Vec<U32String>,
     #[br(if(context.version == Version::V1))]
-    v1: Option<ValueModsV1>,
+    _v1: Option<ValueModsV1>,
     #[br(if(context.version == Version::V3), parse_with(parse_counted))]
     v3: ValueModsV3,
 }
@@ -1811,7 +1811,7 @@ struct FontStyle {
     #[br(parse_with(parse_bool))]
     underline: bool,
     #[br(parse_with(parse_bool))]
-    show: bool,
+    _show: bool,
     #[br(parse_with(parse_color))]
     fg: Color,
     #[br(parse_with(parse_color))]
index 68093aca0b7100a83d42edd2887128fa3c5d12dc..39f737e16f3afea108ae3ddf477e021ef1252d17 100644 (file)
@@ -222,8 +222,10 @@ pub struct Container {
     structure_member: String,
     show: bool,
     page_break_before: bool,
+    #[allow(dead_code)]
     text_align: Option<HorzAlign>,
     command_name: String,
+    #[allow(dead_code)]
     width: Option<Length>,
     label: String,
     content: Content,
@@ -285,6 +287,7 @@ impl Content {
 #[derive(Clone, Debug)]
 pub struct Table {
     subtype: String,
+    #[allow(dead_code)]
     table_type: TableType,
     look: Option<Box<Look>>,
     bin_member: String,
@@ -854,7 +857,7 @@ mod raw {
         #[serde(rename = "@subType")]
         subtype: String,
         #[serde(rename = "@tableId")]
-        table_id: Option<i64>,
+        _table_id: Option<i64>,
         #[serde(rename = "@type")]
         table_type: TableType,
         table_properties: Option<Box<TableProperties>>,
diff --git a/rust/pspp/src/spv/testdata/.gitignore b/rust/pspp/src/spv/testdata/.gitignore
new file mode 100644 (file)
index 0000000..a59f7dc
--- /dev/null
@@ -0,0 +1 @@
+*.actual.svg
\ No newline at end of file
index b26dec0c406b3f70553a348e03ef219e1f3f2e91..f91c87192145ec82e1603aa3cb4abeac321b05c5 100644 (file)
@@ -5,7 +5,7 @@
        <location method="fixed" part="top" value="0px"/>
        <location method="fixed" part="bottom" value="500px"/>
        <extension legend1="frame_legend_1" styleCycleRepository="styleCycleRepository"/>
-       <embeddedSource id="source0"><names>$PERCENT;V4;V8</names><types>double;double;double</types><row>26.31578947368421;1;1</row><row>54.3859649122807;0;2</row><row>19.29824561403509;1;2</row></embeddedSource>
+       <embeddedSource id="source0"><names>$PERCENT;V4;V8</names><types>double;double;double</types><row>26.31578947368421;0;1</row><row>54.3859649122807;1;2</row><row>19.29824561403509;0;2</row></embeddedSource>
        <sourceVariable categorical="true" creator="external_datasource" id="variable4" key="false" label="label1" shortLabel="short1" source="source0" sourceName="V4" weight="false">
                <format>
                        <relabel from="0" id="relabel_1192" to="no"/>
                <location method="fixed" part="bottom" value="99%"/>
                <location method="attach" part="right" target="legendContainer"/>
                <coordinates id="coordinates_1223">
-                       <dimension id="dimension_1224" niceUpperMapping="false"/>
-                       <polarTransform id="polarTransform_1245"/>
+                       <dimension id="dimension_1224" niceUpperMapping="false">
+                               <axis repeat="always" combineAxisLabels="false">
+                                       <label><text>Axis Label</text></label>
+                               </axis>
+                       </dimension>
                </coordinates>
                <faceting id="faceting_1225" method="nest">
                        <cross id="cross_1226">