work
authorBen Pfaff <blp@cs.stanford.edu>
Thu, 23 Oct 2025 15:27:20 +0000 (08:27 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Thu, 23 Oct 2025 15:27:20 +0000 (08:27 -0700)
rust/pspp/src/output/spv/legacy_xml.rs

index d52e1325bdd7465a509b03f15e5d2fad702a01a5..b8bf8a6b6d9dae1d236ede5318f971b560aafb74 100644 (file)
@@ -319,53 +319,16 @@ impl Visualization {
             }
 
             for dv in take(&mut derived_variables) {
-                let mut values = if dv.value == "constant(0)" {
-                    let n_values = if let Some(series) = series.values().next() {
-                        series.values.len()
-                    } else {
-                        derived_variables.push(dv);
-                        continue;
-                    };
-                    (0..n_values)
-                        .map(|_| DataValue {
-                            index: Some(0.0),
-                            value: Datum::Number(Some(0.0)),
-                        })
-                        .collect()
-                } else if dv.value.starts_with("constant") {
-                    vec![]
-                } else if let Some(rest) = dv.value.strip_prefix("map(")
-                    && let Some(var_name) = rest.strip_suffix(")")
-                {
-                    let Some(dependency) = series.get(var_name) else {
-                        derived_variables.push(dv);
-                        continue;
-                    };
-                    dependency.values.clone()
-                } else {
-                    unreachable!()
-                };
-                let mut map = Map::new();
-                map.remap_vmes(&dv.value_map);
-                map.apply(&mut values);
-                map.remap_formats(&dv.format, &dv.string_format);
-                if values
-                    .iter()
-                    .all(|value| value.value.is_string_and(|s| s.is_empty()))
-                {
-                    values.clear();
+                match dv.decode(&data, &series) {
+                    Ok(s) => {
+                        series.insert(&dv.id, s);
+                    }
+                    Err(()) => derived_variables.push(dv),
                 }
-                series.insert(
-                    &dv.id,
-                    Series {
-                        label: None,
-                        format: F8_0,
-                        remapped: false,
-                        values,
-                        map,
-                        affixes: Vec::new(),
-                    },
-                );
+            }
+
+            if n_source == source_variables.len() && n_derived == derived_variables.len() {
+                unreachable!();
             }
         }
 
@@ -498,6 +461,57 @@ struct DerivedVariable {
     value_map: Vec<ValueMapEntry>,
 }
 
+impl DerivedVariable {
+    fn decode(
+        &self,
+        data: &HashMap<String, HashMap<String, Vec<DataValue>>>,
+        series: &HashMap<&str, Series>,
+    ) -> Result<Series, ()> {
+        let mut values = if self.value == "constant(0)" {
+            let n_values = if let Some(series) = series.values().next() {
+                series.values.len()
+            } else {
+                return Err(());
+            };
+            (0..n_values)
+                .map(|_| DataValue {
+                    index: Some(0.0),
+                    value: Datum::Number(Some(0.0)),
+                })
+                .collect()
+        } else if self.value.starts_with("constant") {
+            vec![]
+        } else if let Some(rest) = self.value.strip_prefix("map(")
+            && let Some(var_name) = rest.strip_suffix(")")
+        {
+            let Some(dependency) = series.get(var_name) else {
+                return Err(());
+            };
+            dependency.values.clone()
+        } else {
+            unreachable!()
+        };
+        let mut map = Map::new();
+        map.remap_vmes(&self.value_map);
+        map.apply(&mut values);
+        map.remap_formats(&self.format, &self.string_format);
+        if values
+            .iter()
+            .all(|value| value.value.is_string_and(|s| s.is_empty()))
+        {
+            values.clear();
+        }
+        Ok(Series {
+            label: None,
+            format: F8_0,
+            remapped: false,
+            values,
+            map,
+            affixes: Vec::new(),
+        })
+    }
+}
+
 #[derive(Deserialize, Debug)]
 #[serde(rename = "extension", rename_all = "camelCase")]
 struct VariableExtension {