From 35b5a987e26e2e3b95e2b8a5b3e2160aa31ff17a Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 11 Apr 2025 15:40:50 -0700 Subject: [PATCH] Get rid of data_leaves. --- rust/pspp/src/output/pivot/mod.rs | 76 ++++++++++++++++------------ rust/pspp/src/output/pivot/output.rs | 8 +-- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/rust/pspp/src/output/pivot/mod.rs b/rust/pspp/src/output/pivot/mod.rs index 04a634704b..dc8cfef2dd 100644 --- a/rust/pspp/src/output/pivot/mod.rs +++ b/rust/pspp/src/output/pivot/mod.rs @@ -309,14 +309,6 @@ pub struct Dimension { /// subcategories. pub root: Arc, - /// 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>, - /// 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>, + len: usize, name: Box, /// The child categories. @@ -363,6 +360,25 @@ impl Group { pub fn parent(&self) -> Option> { 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>, leaves: &mut Vec>) -> Arc { + fn build(self, parent: Option>) -> Arc { 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, leaves: &mut Vec>) -> Category { + fn build(self, parent: Weak) -> 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 { diff --git a/rust/pspp/src/output/pivot/output.rs b/rust/pspp/src/output/pivot/output.rs index 84b9d8115e..da60afdb7a 100644 --- a/rust/pspp/src/output/pivot/output.rs +++ b/rust/pspp/src/output/pivot/output.rs @@ -240,7 +240,7 @@ impl PivotTable { .collect::>() .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) -> Vec> { @@ -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) -- 2.30.2