cleanujp
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 3 Jan 2026 23:25:02 +0000 (15:25 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 3 Jan 2026 23:25:02 +0000 (15:25 -0800)
rust/pspp/src/spv/read/legacy_xml.rs

index b986aeecae7f995b0ce704eee09bc666924d52b8..e11dba677214587224f992472cf61f1b586e600c 100644 (file)
@@ -105,10 +105,6 @@ impl<'de, T> Deserialize<'de> for Ref<T> {
 struct Map(HashMap<OrderedFloat<f64>, Datum<String>>);
 
 impl Map {
-    fn new() -> Self {
-        Self::default()
-    }
-
     fn apply(&self, data: &mut Vec<Datum<String>>) {
         for value in data {
             if let Datum::Number(Some(number)) = value
@@ -118,23 +114,6 @@ impl Map {
             }
         }
     }
-
-    fn from_vmes(value_map: &[ValueMapEntry]) -> Self {
-        let mut map = Map::new();
-        for vme in value_map {
-            for from in vme.from.split(';') {
-                if let Ok(from) = from.trim().parse::<f64>() {
-                    let to = if let Ok(to) = vme.to.trim().parse::<f64>() {
-                        Datum::Number(Some(to))
-                    } else {
-                        Datum::String(vme.to.clone())
-                    };
-                    map.0.insert(OrderedFloat(from), to);
-                }
-            }
-        }
-        map
-    }
 }
 
 /// A warning decoding a legacy XML member.
@@ -733,10 +712,7 @@ impl Series {
     fn new_name(&self, datum: &Datum<String>, footnotes: &pivot::Footnotes) -> Value {
         let mut name = Value::new_datum(datum);
         for affix in &self.affixes {
-            if let Some(index) = affix.defines_reference.checked_sub(1)
-                && let Ok(index) = usize::try_from(index)
-                && let Some(footnote) = footnotes.get(index)
-            {
+            if let Some(footnote) = footnotes.get(affix.defines_reference.get() - 1) {
                 name.add_footnote(footnote);
             }
         }
@@ -902,6 +878,30 @@ struct DerivedVariable {
     value_map: Vec<ValueMapEntry>,
 }
 
+impl DerivedVariable {
+    fn mapping(&self) -> Map {
+        Map(self
+            .value_map
+            .iter()
+            .flat_map(|vme| {
+                vme.from
+                    .split(';')
+                    .filter_map(|from| from.trim().parse::<f64>().ok())
+                    .map(|from| {
+                        (
+                            OrderedFloat(from),
+                            if let Ok(to) = vme.to.trim().parse::<f64>() {
+                                Datum::Number(Some(to))
+                            } else {
+                                Datum::String(vme.to.clone())
+                            },
+                        )
+                    })
+            })
+            .collect())
+    }
+}
+
 impl Variable for DerivedVariable {
     fn decode<'a>(
         &'a self,
@@ -950,7 +950,7 @@ impl Variable for DerivedVariable {
             });
             vec![]
         };
-        Map::from_vmes(&self.value_map).apply(&mut values);
+        self.mapping().apply(&mut values);
         if let Some(format) = &self.format {
             format.mapping().apply(&mut values);
         } else if let Some(string_format) = &self.string_format {
@@ -1356,10 +1356,9 @@ enum Scientific {
 #[derive(Clone, Debug, Deserialize)]
 #[serde(rename_all = "camelCase")]
 struct Affix {
-    /// The footnote number as a natural number: 1 for the first footnote, 2 for
-    /// the second, and so on.
+    /// A reference to a footnote with the given 1-based index.
     #[serde(rename = "@definesReference")]
-    defines_reference: u64,
+    defines_reference: NonZeroUsize,
 }
 
 #[derive(Deserialize, Debug)]
@@ -1458,10 +1457,7 @@ impl Style {
             {
                 value.clear_footnotes();
                 for affix in child.affixes() {
-                    if let Some(index) = affix.defines_reference.checked_sub(1)
-                        && let Ok(index) = usize::try_from(index)
-                        && let Some(footnote) = footnotes.get(index)
-                    {
+                    if let Some(footnote) = footnotes.get(affix.defines_reference.get() - 1) {
                         value.add_footnote(footnote);
                     }
                 }