fixes
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 29 Dec 2025 00:04:17 +0000 (16:04 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 29 Dec 2025 00:04:17 +0000 (16:04 -0800)
rust/pspp/src/spv/read/legacy_bin.rs
rust/pspp/src/spv/read/legacy_xml.rs

index e4b7355ca46eadc58acf69b34cd2bd50ac7a429f..ff86015f0351f6a9baa5920bf2d5ca474d06b71d 100644 (file)
@@ -92,7 +92,12 @@ impl DataValue {
     pub fn category(&self) -> Option<usize> {
         match &self.value {
             Datum::Number(number) => *number,
-            _ => self.index,
+            _ if self.index.is_some() => self.index,
+            Datum::String(string) => {
+                // This only comes up in a few cases which indicate something
+                // odd might have happened to the table in the SPV files.
+                string.parse().ok()
+            }
         }
         .and_then(|v| (v >= 0.0 && v < usize::MAX as f64).then_some(v as usize))
     }
index 3b45b634ae2e033e73e5112b27f0f79a32da6b7b..5987b62b6143806c767c2aedddb54f3bc0dcb6c9 100644 (file)
@@ -381,7 +381,6 @@ impl Visualization {
                 && let Some(axis) = axes.get(&(base_level + variables.len()))
                 && let Some(label) = &axis.label
             {
-                dbg!(label);
                 let mut dimension_style = AreaStyle::default_for_area(Area::Labels(a));
                 let style = label.style.get(&styles);
                 let fg = style;
@@ -665,11 +664,14 @@ impl Visualization {
             .footnotes()
             .and_then(|footnotes| series.get(footnotes.variable.as_str()));
         let mut data = HashMap::new();
-        for (i, cell) in cell.values.iter().enumerate() {
+        'outer: for (i, cell) in cell.values.iter().enumerate() {
             coords.clear();
             for dim in &dims {
-                // XXX indexing of values, and unwrap
-                let coordinate = dim.coordinate.values[i].category().unwrap();
+                // XXX indexing of values
+                let Some(coordinate) = dim.coordinate.values[i].category() else {
+                    // XXX issue warning?
+                    continue 'outer;
+                };
                 let Some(index) = dim
                     .coordinate
                     .coordinate_to_index
@@ -695,9 +697,9 @@ impl Visualization {
             };
             let mut value = cell.as_pivot_value(format);
 
-            if let Some(cell_footnotes) = &cell_footnotes {
-                // XXX indexing
-                let dv = &cell_footnotes.values[i];
+            if let Some(cell_footnotes) = &cell_footnotes
+                && let Some(dv) = cell_footnotes.values.get(i)
+            {
                 if let Some(s) = dv.value.as_string() {
                     for part in s.split(',') {
                         if let Ok(index) = part.parse::<usize>()
@@ -766,7 +768,6 @@ impl Visualization {
             impl<'a> Target<'a> {
                 fn decode(
                     &self,
-                    scp: &SetCellProperties,
                     intersect: &Intersect,
                     look: &mut Look,
                     series: &BTreeMap<&str, Series>,
@@ -786,14 +787,12 @@ impl Visualization {
                         }
                     }
 
-                    dbg!(&scp.id, self, intersect);
                     match self {
                         Self {
                             format: Some((_, Some(TargetType::MajorTicks))),
                             ..
                         } if !wheres.is_empty() => {
                             // Formatting for individual row or column labels.
-                            dbg!();
                             for w in &wheres {
                                 let Some(s) = series.get(w.variable.as_str()) else {
                                     continue;
@@ -831,7 +830,6 @@ impl Visualization {
                         } => {
                             // Formatting for individual cells or groups of them
                             // with some dimensions in common.
-                            dbg!(&scp.id);
                             let mut include = vec![HashSet::new(); dims.len()];
                             for w in &wheres {
                                 let Some(s) = series.get(w.variable.as_str()) else {
@@ -883,7 +881,6 @@ impl Visualization {
                                     );
                                 }
                             }
-                            dbg!();
                         }
                         _ => (),
                     }
@@ -912,7 +909,6 @@ impl Visualization {
                     for intersect in &union_.intersects {
                         for target in &targets {
                             target.decode(
-                                scp,
                                 intersect,
                                 &mut look,
                                 &series,
@@ -1104,15 +1100,19 @@ impl SourceVariable {
             None
         };
 
-        let Some(data) = data
-            .get(&self.source)
-            .and_then(|source| source.get(&self.source_name))
-        else {
-            todo!()
+        let data = if let Some(source) = data.get(&self.source)
+            && let Some(values) = source.get(&self.source_name)
+        {
+            values.as_slice()
+        } else {
+            /*
+            XXX warn
+            */
+            &[]
         };
         let mut map = Map::new();
         let (format, affixes) = map.remap_formats(&self.format, &self.string_format);
-        let mut data = data.clone();
+        let mut data = Vec::from(data);
         if !map.0.is_empty() {
             map.apply(&mut data);
         } else if let Some(label_series) = label_series {
@@ -1848,10 +1848,9 @@ impl Style {
     ) {
         if let Some(sf) = sf {
             if let Some(child) = &sf.child
-                && let Some(format) = dbg!(child.decode_format())
+                && let Some(format) = child.decode_format()
                 && let Some(datum_value) = value.inner.as_datum_value_mut()
             {
-                dbg!(&datum_value);
                 match &datum_value.datum {
                     Datum::Number(_) => {
                         datum_value.format = format;
@@ -2524,9 +2523,8 @@ struct Footnotes {
 impl Footnotes {
     fn decode(&self, dst: &mut BTreeMap<usize, Footnote>) {
         for f in &self.mappings {
-            dst.entry(f.defines_reference.get() - 1)
-                .or_default()
-                .content = f.to.clone();
+            let index = f.defines_reference.unwrap_or(f.from).get() - 1;
+            dst.entry(index).or_default().content = f.to.clone();
         }
     }
 }
@@ -2535,10 +2533,10 @@ impl Footnotes {
 #[serde(rename_all = "camelCase")]
 struct FootnoteMapping {
     #[serde(rename = "@definesReference")]
-    defines_reference: NonZeroUsize,
+    defines_reference: Option<NonZeroUsize>,
 
     #[serde(rename = "@from")]
-    from: i64,
+    from: NonZeroUsize,
 
     #[serde(rename = "@to")]
     to: String,
@@ -2583,26 +2581,11 @@ struct MajorTicks {
     #[serde(rename = "@style")]
     style: Ref<Style>,
 
-    #[serde(rename = "@tickFrameStyle")]
-    tick_frame_style: Ref<Style>,
-
     #[serde(rename = "@labelFrequency")]
     label_frequency: Option<i64>,
 
     #[serde(rename = "@stagger")]
     stagger: Option<bool>,
-
-    gridline: Option<Gridline>,
-}
-
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase")]
-struct Gridline {
-    #[serde(rename = "@style")]
-    style: Ref<Style>,
-
-    #[serde(rename = "@zOrder")]
-    z_order: i64,
 }
 
 #[derive(Deserialize, Debug)]