diff --git a/gpui/src/sum_tree/cursor.rs b/gpui/src/sum_tree/cursor.rs index f6f6f9a599c1d502e6a892bbebe70b6b66e92c9f..21855933288e0b84b62b95f09210443eca265923 100644 --- a/gpui/src/sum_tree/cursor.rs +++ b/gpui/src/sum_tree/cursor.rs @@ -1,6 +1,6 @@ use super::*; use arrayvec::ArrayVec; -use std::{cmp::Ordering, sync::Arc}; +use std::{cmp::Ordering, mem, sync::Arc}; #[derive(Clone)] struct StackEntry<'a, T: Item, D> { @@ -324,7 +324,7 @@ where Target: SeekTarget<'a, T::Summary, D>, { self.reset(); - self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx) + self.seek_internal(pos, bias, &mut (), cx) } pub fn seek_forward( @@ -336,7 +336,7 @@ where where Target: SeekTarget<'a, T::Summary, D>, { - self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx) + self.seek_internal(pos, bias, &mut (), cx) } pub fn slice( @@ -348,23 +348,18 @@ where where Target: SeekTarget<'a, T::Summary, D>, { - let mut slice = SeekAggregate::Slice(SumTree::new()); - self.seek_internal::<_, ()>(end, bias, &mut slice, cx); - if let SeekAggregate::Slice(slice) = slice { - slice - } else { - unreachable!() - } + let mut slice = SliceSeekAggregate { + tree: SumTree::new(), + leaf_items: ArrayVec::new(), + leaf_item_summaries: ArrayVec::new(), + leaf_summary: T::Summary::default(), + }; + self.seek_internal(end, bias, &mut slice, cx); + slice.tree } pub fn suffix(&mut self, cx: &::Context) -> SumTree { - let mut slice = SeekAggregate::Slice(SumTree::new()); - self.seek_internal::<_, ()>(&End::new(), Bias::Right, &mut slice, cx); - if let SeekAggregate::Slice(slice) = slice { - slice - } else { - unreachable!() - } + self.slice(&End::new(), Bias::Right, cx) } pub fn summary( @@ -377,26 +372,18 @@ where Target: SeekTarget<'a, T::Summary, D>, Output: Dimension<'a, T::Summary>, { - let mut summary = SeekAggregate::Summary(Output::default()); + let mut summary = SummarySeekAggregate(Output::default()); self.seek_internal(end, bias, &mut summary, cx); - if let SeekAggregate::Summary(summary) = summary { - summary - } else { - unreachable!() - } + summary.0 } - fn seek_internal( + fn seek_internal( &mut self, - target: &Target, + target: &dyn SeekTarget<'a, T::Summary, D>, bias: Bias, - aggregate: &mut SeekAggregate, + aggregate: &mut dyn SeekAggregate<'a, T>, cx: &::Context, - ) -> bool - where - Target: SeekTarget<'a, T::Summary, D>, - Output: Dimension<'a, T::Summary>, - { + ) -> bool { debug_assert!( target.cmp(&self.position, cx) >= Ordering::Equal, "cannot seek backward from {:?} to {:?}", @@ -437,15 +424,7 @@ where || (comparison == Ordering::Equal && bias == Bias::Right) { self.position = child_end; - match aggregate { - SeekAggregate::None => {} - SeekAggregate::Slice(slice) => { - slice.push_tree(child_tree.clone(), cx); - } - SeekAggregate::Summary(summary) => { - summary.add_summary(child_summary, cx); - } - } + aggregate.push_tree(child_tree, child_summary, cx); entry.index += 1; entry.position = self.position.clone(); } else { @@ -464,12 +443,7 @@ where ref item_summaries, .. } => { - let mut slice_items = ArrayVec::::new(); - let mut slice_item_summaries = ArrayVec::::new(); - let mut slice_items_summary = match aggregate { - SeekAggregate::Slice(_) => Some(T::Summary::default()), - _ => None, - }; + aggregate.begin_leaf(); for (item, item_summary) in items[entry.index..] .iter() @@ -483,49 +457,15 @@ where || (comparison == Ordering::Equal && bias == Bias::Right) { self.position = child_end; - match aggregate { - SeekAggregate::None => {} - SeekAggregate::Slice(_) => { - slice_items.push(item.clone()); - slice_item_summaries.push(item_summary.clone()); - ::add_summary( - slice_items_summary.as_mut().unwrap(), - item_summary, - cx, - ); - } - SeekAggregate::Summary(summary) => { - summary.add_summary(item_summary, cx); - } - } + aggregate.push_item(item, item_summary, cx); entry.index += 1; } else { - if let SeekAggregate::Slice(slice) = aggregate { - slice.push_tree( - SumTree(Arc::new(Node::Leaf { - summary: slice_items_summary.unwrap(), - items: slice_items, - item_summaries: slice_item_summaries, - })), - cx, - ); - } + aggregate.end_leaf(cx); break 'outer; } } - if let SeekAggregate::Slice(slice) = aggregate { - if !slice_items.is_empty() { - slice.push_tree( - SumTree(Arc::new(Node::Leaf { - summary: slice_items_summary.unwrap(), - items: slice_items, - item_summaries: slice_item_summaries, - })), - cx, - ); - } - } + aggregate.end_leaf(cx); } } @@ -625,8 +565,81 @@ where } } -enum SeekAggregate { - None, - Slice(SumTree), - Summary(D), +trait SeekAggregate<'a, T: Item> { + fn begin_leaf(&mut self); + fn end_leaf(&mut self, cx: &::Context); + fn push_item( + &mut self, + item: &'a T, + summary: &'a T::Summary, + cx: &::Context, + ); + fn push_tree( + &mut self, + tree: &'a SumTree, + summary: &'a T::Summary, + cx: &::Context, + ); +} + +struct SliceSeekAggregate { + tree: SumTree, + leaf_items: ArrayVec, + leaf_item_summaries: ArrayVec, + leaf_summary: T::Summary, +} + +struct SummarySeekAggregate(D); + +impl<'a, T: Item> SeekAggregate<'a, T> for () { + fn begin_leaf(&mut self) {} + fn end_leaf(&mut self, _: &::Context) {} + fn push_item(&mut self, _: &T, _: &T::Summary, _: &::Context) {} + fn push_tree(&mut self, _: &SumTree, _: &T::Summary, _: &::Context) {} +} + +impl<'a, T: Item> SeekAggregate<'a, T> for SliceSeekAggregate { + fn begin_leaf(&mut self) {} + fn end_leaf(&mut self, cx: &::Context) { + self.tree.push_tree( + SumTree(Arc::new(Node::Leaf { + summary: mem::take(&mut self.leaf_summary), + items: mem::take(&mut self.leaf_items), + item_summaries: mem::take(&mut self.leaf_item_summaries), + })), + cx, + ); + } + fn push_item(&mut self, item: &T, summary: &T::Summary, cx: &::Context) { + self.leaf_items.push(item.clone()); + self.leaf_item_summaries.push(summary.clone()); + Summary::add_summary(&mut self.leaf_summary, summary, cx); + } + fn push_tree( + &mut self, + tree: &SumTree, + _: &T::Summary, + cx: &::Context, + ) { + self.tree.push_tree(tree.clone(), cx); + } +} + +impl<'a, T: Item, D> SeekAggregate<'a, T> for SummarySeekAggregate +where + D: Dimension<'a, T::Summary>, +{ + fn begin_leaf(&mut self) {} + fn end_leaf(&mut self, _: &::Context) {} + fn push_item(&mut self, _: &T, summary: &'a T::Summary, cx: &::Context) { + self.0.add_summary(summary, cx); + } + fn push_tree( + &mut self, + _: &SumTree, + summary: &'a T::Summary, + cx: &::Context, + ) { + self.0.add_summary(summary, cx); + } }