Get rid of data_leaves.
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 11 Apr 2025 22:40:50 +0000 (15:40 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 11 Apr 2025 22:40:50 +0000 (15:40 -0700)
rust/pspp/src/output/pivot/mod.rs
rust/pspp/src/output/pivot/output.rs

index 04a634704b24b86da8c52e1fe70aeaaae096cc69..dc8cfef2ddf214ec4c21e9b7eb121083de7a96a1 100644 (file)
@@ -309,14 +309,6 @@ pub struct Dimension {
     /// subcategories.
     pub root: Arc<Group>,
 
-    ///  All of the leaves reachable via the root.
-    ///
-    ///  The indexing for `data_leaves` is that used for `idx` in [Cell], thus
-    ///  `data_leaves[i]->data_index == i`.  This might differ from what an
-    ///  in-order traversal of `root` would yield, if the user reordered
-    ///  categories.
-    data_leaves: Vec<Arc<Leaf>>,
-
     /// Ordering of leaves for presentation.
     ///
     /// This is a permutation of `0..n` where `n` is the number of leaves.
@@ -332,7 +324,11 @@ impl Dimension {
     }
 
     pub fn len(&self) -> usize {
-        self.data_leaves.len()
+        self.root.len()
+    }
+
+    pub fn nth_leaf(&self, index: usize) -> Option<&Leaf> {
+        self.root.nth_leaf(index)
     }
 
     pub fn builder(axis: Axis3, root: GroupBuilder) -> DimensionBuilder {
@@ -343,6 +339,7 @@ impl Dimension {
 #[derive(Clone, Debug)]
 pub struct Group {
     parent: Option<Weak<Group>>,
+    len: usize,
     name: Box<Value>,
 
     /// The child categories.
@@ -363,6 +360,25 @@ impl Group {
     pub fn parent(&self) -> Option<Arc<Group>> {
         self.parent.as_ref().map(|parent| parent.upgrade().unwrap())
     }
+
+    pub fn nth_leaf(&self, mut index: usize) -> Option<&Leaf> {
+        for child in &self.children {
+            let len = child.len();
+            if index < len {
+                return child.nth_leaf(index);
+            }
+            index -= len;
+        }
+        None
+    }
+
+    pub fn len(&self) -> usize {
+        self.len
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
 }
 
 #[derive(Clone)]
@@ -373,14 +389,12 @@ pub struct DimensionBuilder {
 
 impl DimensionBuilder {
     pub fn new(axis: Axis3, root: GroupBuilder) -> Self {
-        let mut leaves = Vec::with_capacity(root.len());
-        let root = root.build(None, &mut leaves);
+        let root = root.build(None);
         Self {
             axis,
             dimension: Dimension {
+                presentation_order: (0..root.len()).collect(),
                 root,
-                presentation_order: (0..leaves.len()).collect(),
-                data_leaves: leaves,
                 hide_all_labels: false,
             },
         }
@@ -435,13 +449,14 @@ impl GroupBuilder {
     fn len(&self) -> usize {
         self.children.iter().map(|category| category.len()).sum()
     }
-    fn build(self, parent: Option<Weak<Group>>, leaves: &mut Vec<Arc<Leaf>>) -> Arc<Group> {
+    fn build(self, parent: Option<Weak<Group>>) -> Arc<Group> {
         Arc::new_cyclic(|weak| Group {
+            len: self.children.iter().map(|c| c.len()).sum(),
             name: self.name,
             children: self
                 .children
                 .into_iter()
-                .map(|c| c.build(weak.clone(), leaves))
+                .map(|c| c.build(weak.clone()))
                 .collect(),
             show_label: {
                 // By default, nested group labels are shown, but not dimension root labels.
@@ -468,16 +483,15 @@ impl CategoryBuilder {
             CategoryBuilder::Leaf { .. } => 1,
         }
     }
-    fn build(self, parent: Weak<Group>, leaves: &mut Vec<Arc<Leaf>>) -> Category {
+    fn build(self, parent: Weak<Group>) -> Category {
         match self {
-            Self::Group(group) => Category::Group(group.build(Some(parent), leaves)),
+            Self::Group(group) => Category::Group(group.build(Some(parent))),
             Self::Leaf { name, class } => {
                 let leaf = Arc::new(Leaf {
                     parent,
                     name,
                     class,
                 });
-                leaves.push(leaf.clone());
                 Category::Leaf(leaf)
             }
         }
@@ -661,17 +675,23 @@ pub enum Category {
 }
 
 impl Category {
-    fn is_leaf(&self) -> bool {
+    fn len(&self) -> usize {
         match self {
-            Category::Group(_) => false,
-            Category::Leaf(_) => true,
+            Category::Group(group) => group.len,
+            Category::Leaf(leaf) => 1,
         }
     }
 
-    fn is_group(&self) -> bool {
+    fn nth_leaf(&self, index: usize) -> Option<&Leaf> {
         match self {
-            Category::Group(_) => true,
-            Category::Leaf(_) => false,
+            Category::Group(group) => group.nth_leaf(index),
+            Category::Leaf(leaf) => {
+                if index == 0 {
+                    Some(&leaf)
+                } else {
+                    None
+                }
+            }
         }
     }
 
@@ -681,14 +701,6 @@ impl Category {
             Category::Leaf(_) => true,
         }
     }
-
-    fn ptr_eq(&self, other: &Self) -> bool {
-        match (self, other) {
-            (Category::Group(a), Category::Group(b)) => Arc::ptr_eq(a, b),
-            (Category::Leaf(a), Category::Leaf(b)) => Arc::ptr_eq(a, b),
-            _ => false,
-        }
-    }
 }
 
 trait CategoryTrait {
index 84b9d8115eb3062bd369a8a2afc3ac80826f1ae7..da60afdb7abea6178f7c1e34521a5910e41f799c 100644 (file)
@@ -240,7 +240,7 @@ impl PivotTable {
                 .collect::<Vec<_>>()
                 .into_iter()
                 .enumerate()
-                .map(|(i, dimension)| dimension.data_leaves[layer_indexes[i]].name.clone()),
+                .map(|(i, dimension)| dimension.nth_leaf(layer_indexes[i]).unwrap().name.clone()),
         )
     }
 
@@ -293,7 +293,7 @@ impl PivotTable {
             .iter()
             .rev()
             .map(|index| &self.dimensions[*index])
-            .filter(|d| !d.data_leaves.is_empty())
+            .filter(|d| !d.root.is_empty())
     }
 
     fn collect_footnotes<'a>(&self, tables: impl Iterator<Item = &'a Table>) -> Vec<Arc<Footnote>> {
@@ -358,7 +358,9 @@ impl<'a> Heading<'a> {
         let mut columns = Vec::new();
         let mut height = 0;
         for indexes in column_enumeration.iter() {
-            let leaf = &*dimension.data_leaves[dimension.presentation_order[indexes[dim_index]]];
+            let leaf = dimension
+                .nth_leaf(dimension.presentation_order[indexes[dim_index]])
+                .unwrap();
             let mut groups = leaf
                 .ancestors()
                 .filter(|group| group.show_label)