Skip to main content

gpui_kit_grid/engine/
aggregate.rs

1//! Aggregates of groups and of the whole view. No GPUI types.
2//!
3//! Every job computes them afresh, with no incremental `+new - old`, so a
4//! float sum does not drift. A group of the last level adds its rows; an
5//! upper group, and the totals, merge their subgroups' partial sums in key
6//! order.
7
8use std::{cmp::Ordering, fmt, mem, ops::Range, sync::Arc};
9
10#[cfg(feature = "decimal")]
11use rust_decimal::{Decimal, prelude::ToPrimitive as _};
12
13use super::{
14    Projection, ViewSpec,
15    display::{AggregateValues, GroupData},
16};
17use crate::{
18    model::{CellValue, ColumnSet, GridColumns, GridRow, OwnedValue},
19    store::{RowId, StoreSnapshot},
20};
21
22/// A custom aggregate for [`Aggregate::Custom`]: a weighted average, a
23/// median. Called in the background, from several threads of a large
24/// rebuild, once per group.
25pub trait AggregateFn<R: GridRow>: Send + Sync + 'static {
26    /// The aggregate of `column` over the live rows of one group, or of the
27    /// whole view for the totals.
28    fn aggregate(&self, column: R::Column, rows: &mut dyn Iterator<Item = &R>) -> OwnedValue;
29
30    /// The aggregate of a group from its subgroups' aggregates, when the
31    /// function allows it (a sum does, a median does not). `None`, the
32    /// default: the group's rows are iterated.
33    fn combine(&self, _parts: &[&OwnedValue]) -> Option<OwnedValue> {
34        None
35    }
36
37    /// The columns whose changes change the aggregate of `column`: that
38    /// column by default.
39    fn depends_on(&self, column: R::Column) -> ColumnSet {
40        let mut columns = ColumnSet::EMPTY;
41        columns.insert(column.ix());
42        columns
43    }
44
45    /// The name a tooltip and a screen reader give the aggregate
46    /// ("Weighted average"); empty by default.
47    fn name(&self) -> &str {
48        ""
49    }
50}
51
52/// The aggregate of a column, for group captions, group footers and the
53/// totals. Every job computes them afresh over the live rows; without a
54/// value to aggregate, they are `Empty` (a `Count`, `Int(0)`).
55#[non_exhaustive]
56pub enum Aggregate<R: GridRow> {
57    /// The sum of the numbers: an `Int` over integers while it fits in an
58    /// `i64` (added exactly), a `Float` once a float is among them or it
59    /// overflows. With the `decimal` feature, decimals and integers add up
60    /// exactly to a `Decimal`, a `Float` once a float is among them or the
61    /// sum overflows a `Decimal`. Text, booleans and blanks are skipped.
62    Sum,
63    /// The mean of the numbers, a `Float`; of decimals and integers alone, a
64    /// `Decimal` rounded to two places more than the largest scale among
65    /// them.
66    Avg,
67    /// The smallest value that is not `Empty`, by `CellValue::cmp_total`.
68    Min,
69    /// The largest value that is not `Empty`, by `CellValue::cmp_total`.
70    Max,
71    /// The number of values that are not `Empty`, as SQL's
72    /// `COUNT(column)`; a group's rows are `GroupInfo::row_count`.
73    Count,
74    /// The application's aggregate.
75    Custom(Arc<dyn AggregateFn<R>>),
76}
77
78impl<R: GridRow> Clone for Aggregate<R> {
79    fn clone(&self) -> Self {
80        match self {
81            Self::Sum => Self::Sum,
82            Self::Avg => Self::Avg,
83            Self::Min => Self::Min,
84            Self::Max => Self::Max,
85            Self::Count => Self::Count,
86            Self::Custom(function) => Self::Custom(function.clone()),
87        }
88    }
89}
90
91impl<R: GridRow> fmt::Debug for Aggregate<R> {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        match self {
94            Self::Sum => f.write_str("Sum"),
95            Self::Avg => f.write_str("Avg"),
96            Self::Min => f.write_str("Min"),
97            Self::Max => f.write_str("Max"),
98            Self::Count => f.write_str("Count"),
99            Self::Custom(function) => f.debug_tuple("Custom").field(&function.name()).finish(),
100        }
101    }
102}
103
104impl<R: GridRow> Aggregate<R> {
105    /// The columns whose changes change this aggregate of `column`.
106    pub(super) fn depends_on(&self, column: R::Column) -> ColumnSet {
107        match self {
108            Self::Custom(function) => function.depends_on(column),
109            Self::Sum | Self::Avg | Self::Min | Self::Max | Self::Count => {
110                let mut columns = ColumnSet::EMPTY;
111                columns.insert(column.ix());
112                columns
113            }
114        }
115    }
116}
117
118impl<R: GridRow> ViewSpec<R> {
119    /// Aggregates these columns, for group captions, group footers and the
120    /// totals. A repeated column keeps its last aggregate. The aggregates
121    /// survive a change of grouping or tree. A view without grouping has
122    /// totals too.
123    pub fn with_aggregates(
124        mut self,
125        aggregates: impl IntoIterator<Item = (R::Column, Aggregate<R>)>,
126    ) -> Self {
127        let mut unique: Vec<(R::Column, Aggregate<R>)> = Vec::new();
128        for (column, aggregate) in aggregates {
129            match unique.iter_mut().find(|(kept, _)| *kept == column) {
130                Some(kept) => kept.1 = aggregate,
131                None => unique.push((column, aggregate)),
132            }
133        }
134        self.aggregates = (!unique.is_empty()).then(|| unique.into());
135        self
136    }
137
138    /// The aggregates by column.
139    pub fn aggregates(&self) -> &[(R::Column, Aggregate<R>)] {
140        self.aggregates.as_deref().unwrap_or_default()
141    }
142
143    /// The columns whose changes change aggregates: the aggregated columns
144    /// and what custom aggregates depend on.
145    pub fn aggregate_columns(&self) -> ColumnSet {
146        let mut columns = ColumnSet::EMPTY;
147        for (column, aggregate) in self.aggregates() {
148            columns.union_with(aggregate.depends_on(*column));
149        }
150        columns
151    }
152}
153
154/// The aggregates of a view, in the schema order of their columns: the
155/// order of an [`AggregateValues`] run.
156pub(super) struct ViewAggregates<'s, R: GridRow> {
157    columns: ColumnSet,
158    list: Vec<(R::Column, &'s Aggregate<R>)>,
159    /// Places in `list` of the built-in aggregates, computed row by row.
160    built_in: Vec<usize>,
161    /// Places in `list` of the custom ones, computed once per group.
162    custom: Vec<(usize, &'s dyn AggregateFn<R>)>,
163}
164
165impl<'s, R: GridRow> ViewAggregates<'s, R> {
166    pub(super) fn new(spec: &'s ViewSpec<R>) -> Self {
167        let mut list: Vec<(R::Column, &Aggregate<R>)> = spec
168            .aggregates()
169            .iter()
170            .map(|(column, aggregate)| (*column, aggregate))
171            .collect();
172        list.sort_by_key(|(column, _)| column.ix());
173        let mut columns = ColumnSet::EMPTY;
174        let mut built_in = Vec::new();
175        let mut custom = Vec::new();
176        for (ix, (column, aggregate)) in list.iter().enumerate() {
177            columns.insert(column.ix());
178            match aggregate {
179                Aggregate::Custom(function) => custom.push((ix, &**function)),
180                Aggregate::Sum
181                | Aggregate::Avg
182                | Aggregate::Min
183                | Aggregate::Max
184                | Aggregate::Count => built_in.push(ix),
185            }
186        }
187        Self {
188            columns,
189            list,
190            built_in,
191            custom,
192        }
193    }
194
195    /// The aggregated columns.
196    pub(super) fn columns(&self) -> ColumnSet {
197        self.columns
198    }
199
200    /// Returns true if the view aggregates nothing.
201    pub(super) fn is_empty(&self) -> bool {
202        self.list.is_empty()
203    }
204
205    /// A fresh partial per aggregate.
206    fn start<'a>(&self) -> impl Iterator<Item = Partial<'a>> + '_ {
207        self.list
208            .iter()
209            .map(|(_, aggregate)| Partial::start(aggregate))
210    }
211
212    /// Adds `row` to the built-in partials of one run.
213    #[inline]
214    fn add<'a>(&self, partials: &mut [Partial<'a>], row: &'a R) {
215        for &ix in &self.built_in {
216            partials[ix].add(row.value(self.list[ix].0));
217        }
218    }
219
220    /// Merges the built-in partials of `part` into `partials`.
221    fn merge<'a>(&self, partials: &mut [Partial<'a>], part: &[Partial<'a>]) {
222        for &ix in &self.built_in {
223            partials[ix].merge(&part[ix]);
224        }
225    }
226
227    /// Writes the built-in results of `partials` into `values`.
228    fn finish(&self, partials: &[Partial<'_>], values: &mut [OwnedValue]) {
229        for &ix in &self.built_in {
230            values[ix] = partials[ix].finish();
231        }
232    }
233}
234
235/// What a built-in aggregate keeps while a job adds rows to it: its partial
236/// sums. Extremes borrow their values from the snapshot's rows, so a group
237/// allocates only for its final text.
238#[derive(Clone, Copy, Debug)]
239enum Partial<'a> {
240    Sum(Numbers),
241    Avg(Numbers),
242    /// The smallest value so far; `Empty` for none (no other value is).
243    Min(CellValue<'a>),
244    /// The largest value so far; `Empty` for none.
245    Max(CellValue<'a>),
246    /// Values that are not `Empty`.
247    Count(u64),
248    /// A custom aggregate keeps nothing: it reads rows or its parts.
249    Custom,
250}
251
252/// The numbers of a sum or a mean: integers and decimals exactly, floats
253/// apart. A sum adds floats in the order rows and then groups come, so it
254/// is the same on every run.
255#[derive(Clone, Copy, Debug, Default)]
256struct Numbers {
257    int: i128,
258    float: f64,
259    has_float: bool,
260    count: u64,
261    #[cfg(feature = "decimal")]
262    decimal: Decimals,
263}
264
265impl Numbers {
266    fn add(&mut self, value: CellValue<'_>) {
267        match value {
268            CellValue::Int(value) => {
269                self.int += i128::from(value);
270                self.count += 1;
271            }
272            CellValue::Float(value) => {
273                self.float += value;
274                self.has_float = true;
275                self.count += 1;
276            }
277            #[cfg(feature = "decimal")]
278            CellValue::Decimal(value) => {
279                self.decimal.add(value);
280                self.count += 1;
281            }
282            // Text, booleans and blanks are not numbers.
283            _ => {}
284        }
285    }
286
287    fn merge(&mut self, other: &Self) {
288        self.int += other.int;
289        self.float += other.float;
290        self.has_float |= other.has_float;
291        self.count += other.count;
292        #[cfg(feature = "decimal")]
293        self.decimal.merge(&other.decimal);
294    }
295
296    /// The sum: `Int` while there are integers alone and it fits, `Decimal`
297    /// while there are decimals and integers alone and it fits, `Float`
298    /// otherwise; `Empty` without numbers.
299    fn sum(&self) -> OwnedValue {
300        if self.count == 0 {
301            return OwnedValue::Empty;
302        }
303        #[cfg(feature = "decimal")]
304        if self.decimal.has_values && !self.has_float {
305            return self
306                .decimal
307                .exact_sum(self.int)
308                .map_or_else(OwnedValue::Float, OwnedValue::Decimal);
309        }
310        if self.has_float {
311            OwnedValue::Float(self.float_sum())
312        } else {
313            i64::try_from(self.int).map_or(OwnedValue::Float(self.int as f64), OwnedValue::Int)
314        }
315    }
316
317    /// The mean: a `Decimal` over decimals and integers alone, a `Float`
318    /// otherwise; `Empty` without numbers.
319    fn mean(&self) -> OwnedValue {
320        if self.count == 0 {
321            return OwnedValue::Empty;
322        }
323        #[cfg(feature = "decimal")]
324        if self.decimal.has_values && !self.has_float {
325            return self
326                .decimal
327                .mean(self.int, self.count)
328                .map_or_else(OwnedValue::Float, OwnedValue::Decimal);
329        }
330        OwnedValue::Float(self.float_sum() / self.count as f64)
331    }
332
333    /// Every number added as a float.
334    fn float_sum(&self) -> f64 {
335        let sum = self.float + self.int as f64;
336        #[cfg(feature = "decimal")]
337        if self.decimal.has_values {
338            return sum + self.decimal.sum.to_f64();
339        }
340        sum
341    }
342}
343
344/// The decimals of a sum or a mean: added exactly, so money has no float drift.
345#[cfg(feature = "decimal")]
346#[derive(Clone, Copy, Debug, Default)]
347struct Decimals {
348    sum: DecimalSum,
349    /// The largest scale among the values: a mean keeps two places more.
350    scale: u32,
351    has_values: bool,
352}
353
354/// A sum of decimals: exact until it overflows a `Decimal` (about 7.9 ×
355/// 10^28), a float from then on, as an `Int` sum that overflows `i64`.
356#[cfg(feature = "decimal")]
357#[derive(Clone, Copy, Debug)]
358enum DecimalSum {
359    Exact(Decimal),
360    Overflow(f64),
361}
362
363#[cfg(feature = "decimal")]
364impl Default for DecimalSum {
365    fn default() -> Self {
366        Self::Exact(Decimal::ZERO)
367    }
368}
369
370#[cfg(feature = "decimal")]
371impl DecimalSum {
372    fn plus(self, other: Self) -> Self {
373        match (self, other) {
374            (Self::Exact(a), Self::Exact(b)) => a
375                .checked_add(b)
376                .map_or_else(|| Self::Overflow(as_f64(a) + as_f64(b)), Self::Exact),
377            (a, b) => Self::Overflow(a.to_f64() + b.to_f64()),
378        }
379    }
380
381    fn to_f64(self) -> f64 {
382        match self {
383            Self::Exact(sum) => as_f64(sum),
384            Self::Overflow(sum) => sum,
385        }
386    }
387}
388
389#[cfg(feature = "decimal")]
390fn as_f64(value: Decimal) -> f64 {
391    value.to_f64().unwrap_or_default()
392}
393
394#[cfg(feature = "decimal")]
395impl Decimals {
396    fn add(&mut self, value: Decimal) {
397        self.sum = self.sum.plus(DecimalSum::Exact(value));
398        self.scale = self.scale.max(value.scale());
399        self.has_values = true;
400    }
401
402    fn merge(&mut self, other: &Self) {
403        if other.has_values {
404            self.sum = self.sum.plus(other.sum);
405            self.scale = self.scale.max(other.scale);
406            self.has_values = true;
407        }
408    }
409
410    /// The sum with the integers `int`: the exact `Decimal`, or the float of
411    /// a sum too large for one.
412    fn exact_sum(&self, int: i128) -> Result<Decimal, f64> {
413        let int = Decimal::try_from_i128_with_scale(int, 0)
414            .map_or_else(|_| DecimalSum::Overflow(int as f64), DecimalSum::Exact);
415        match self.sum.plus(int) {
416            DecimalSum::Exact(sum) => Ok(sum),
417            DecimalSum::Overflow(sum) => Err(sum),
418        }
419    }
420
421    /// The mean of `count` values that add up to the decimals and `int`,
422    /// rounded to two places more than the largest scale; a float when the
423    /// sum is too large.
424    fn mean(&self, int: i128, count: u64) -> Result<Decimal, f64> {
425        let sum = self.exact_sum(int).map_err(|sum| sum / count as f64)?;
426        sum.checked_div(Decimal::from(count))
427            .map(|mean| mean.round_dp(self.scale + 2))
428            .ok_or_else(|| as_f64(sum) / count as f64)
429    }
430}
431
432impl<'a> Partial<'a> {
433    fn start<R: GridRow>(aggregate: &Aggregate<R>) -> Self {
434        match aggregate {
435            Aggregate::Sum => Self::Sum(Numbers::default()),
436            Aggregate::Avg => Self::Avg(Numbers::default()),
437            Aggregate::Min => Self::Min(CellValue::Empty),
438            Aggregate::Max => Self::Max(CellValue::Empty),
439            Aggregate::Count => Self::Count(0),
440            Aggregate::Custom(_) => Self::Custom,
441        }
442    }
443
444    #[inline]
445    fn add(&mut self, value: CellValue<'a>) {
446        match self {
447            Self::Sum(numbers) | Self::Avg(numbers) => numbers.add(value),
448            Self::Min(min) => keep_extreme(min, value, Ordering::Less),
449            Self::Max(max) => keep_extreme(max, value, Ordering::Greater),
450            Self::Count(count) => *count += u64::from(!matches!(value, CellValue::Empty)),
451            Self::Custom => {}
452        }
453    }
454
455    fn merge(&mut self, other: &Self) {
456        match (self, other) {
457            (Self::Sum(numbers), Self::Sum(other)) | (Self::Avg(numbers), Self::Avg(other)) => {
458                numbers.merge(other)
459            }
460            (Self::Min(min), Self::Min(other)) => keep_extreme(min, *other, Ordering::Less),
461            (Self::Max(max), Self::Max(other)) => keep_extreme(max, *other, Ordering::Greater),
462            (Self::Count(count), Self::Count(other)) => *count += other,
463            _ => {}
464        }
465    }
466
467    fn finish(&self) -> OwnedValue {
468        match self {
469            Self::Sum(numbers) => numbers.sum(),
470            Self::Avg(numbers) => numbers.mean(),
471            Self::Min(value) | Self::Max(value) => OwnedValue::from_cell(*value),
472            Self::Count(count) => OwnedValue::Int(i64::try_from(*count).unwrap_or(i64::MAX)),
473            Self::Custom => OwnedValue::Empty,
474        }
475    }
476}
477
478/// Keeps `value` in `extreme` if it is a value and goes further in `side`
479/// than the one kept: on a tie the first stays.
480#[inline]
481fn keep_extreme<'a>(extreme: &mut CellValue<'a>, value: CellValue<'a>, side: Ordering) {
482    if !matches!(value, CellValue::Empty)
483        && (matches!(extreme, CellValue::Empty) || value.cmp_total(extreme) == side)
484    {
485        *extreme = value;
486    }
487}
488
489/// A group as aggregates see it, in key order: before its subgroups, and
490/// siblings in the order of their keys, before the group order sorts them.
491#[derive(Clone, Debug)]
492pub(super) struct KeyedGroup {
493    pub(super) depth: u16,
494    /// The group past its last subgroup, in key order.
495    pub(super) end: u32,
496    /// Its rows; read at the last level only.
497    pub(super) rows: Range<u32>,
498}
499
500/// The aggregates of the groups of a view and its totals.
501pub(super) struct GroupValues {
502    /// A run of values per group, in key order.
503    pub(super) values: Vec<OwnedValue>,
504    /// The live rows of each group, in key order.
505    pub(super) live: Vec<u32>,
506    /// The totals' run.
507    pub(super) totals: Vec<OwnedValue>,
508    /// The live rows of the view.
509    pub(super) total_live: usize,
510}
511
512/// Aggregates `groups`, listed in key order over `rows`, from the bottom
513/// up: a group of the last level adds its live rows (`row` gives `None` for
514/// a row the snapshot no longer has), an upper group merges its subgroups'
515/// partials in key order, and the totals merge the top level's. So the
516/// result depends neither on the group order nor on the number of threads.
517///
518/// A custom aggregate combines its subgroups' values when it can
519/// ([`AggregateFn::combine`]); otherwise it reads the group's rows, in key
520/// order too.
521pub(super) fn aggregate_groups<'r, 'a, R: GridRow, T>(
522    aggregates: &ViewAggregates<'_, R>,
523    groups: &[KeyedGroup],
524    levels: u16,
525    rows: &'r [T],
526    row: impl Fn(&'r T) -> Option<&'a R> + Copy,
527) -> GroupValues {
528    let width = aggregates.list.len();
529    let is_leaf = |group: &KeyedGroup| usize::from(group.depth) + 1 == usize::from(levels);
530    // The live rows of the last-level groups in `span`, in key order.
531    let rows_of = |span: Range<usize>| {
532        groups[span]
533            .iter()
534            .filter(move |group| is_leaf(group))
535            .flat_map(move |group| {
536                rows[group.rows.start as usize..group.rows.end as usize]
537                    .iter()
538                    .filter_map(row)
539            })
540    };
541    let mut partials: Vec<Partial<'a>> = Vec::with_capacity(groups.len() * width);
542    for _ in groups {
543        partials.extend(aggregates.start());
544    }
545    let mut values = vec![OwnedValue::Empty; groups.len() * width];
546    let mut live = vec![0u32; groups.len()];
547
548    for (ix, group) in groups.iter().enumerate().rev() {
549        let run = ix * width..(ix + 1) * width;
550        if is_leaf(group) {
551            let partial = &mut partials[run.clone()];
552            for row in rows_of(ix..ix + 1) {
553                live[ix] += 1;
554                aggregates.add(partial, row);
555            }
556            for &(place, function) in &aggregates.custom {
557                let column = aggregates.list[place].0;
558                values[ix * width + place] = function.aggregate(column, &mut rows_of(ix..ix + 1));
559            }
560        } else {
561            let span = ix + 1..group.end as usize;
562            // Subgroups come after the group, so they are done.
563            let (head, tail) = partials.split_at_mut((ix + 1) * width);
564            let mut child = span.start;
565            while child < span.end {
566                live[ix] += live[child];
567                let part = (child - span.start) * width;
568                aggregates.merge(&mut head[run.clone()], &tail[part..part + width]);
569                child = groups[child].end as usize;
570            }
571            for &(place, function) in &aggregates.custom {
572                let column = aggregates.list[place].0;
573                let (head, tail) = values.split_at_mut((ix + 1) * width);
574                let parts = children(groups, span.clone())
575                    .map(|child| &tail[(child - span.start) * width + place])
576                    .collect::<Vec<_>>();
577                head[ix * width + place] = function
578                    .combine(&parts)
579                    .unwrap_or_else(|| function.aggregate(column, &mut rows_of(span.clone())));
580            }
581        }
582        aggregates.finish(&partials[run.clone()], &mut values[run]);
583    }
584
585    // The totals from the top level's groups, in key order.
586    let mut total: Vec<Partial<'a>> = aggregates.start().collect();
587    let mut total_live = 0;
588    for top in children(groups, 0..groups.len()) {
589        total_live += live[top] as usize;
590        aggregates.merge(&mut total, &partials[top * width..(top + 1) * width]);
591    }
592    let mut totals = vec![OwnedValue::Empty; width];
593    aggregates.finish(&total, &mut totals);
594    for &(place, function) in &aggregates.custom {
595        let column = aggregates.list[place].0;
596        let parts = children(groups, 0..groups.len())
597            .map(|top| &values[top * width + place])
598            .collect::<Vec<_>>();
599        // A view without groups has nothing to combine: its rows, none.
600        totals[place] = (!parts.is_empty())
601            .then(|| function.combine(&parts))
602            .flatten()
603            .unwrap_or_else(|| function.aggregate(column, &mut rows_of(0..groups.len())));
604    }
605    GroupValues {
606        values,
607        live,
608        totals,
609        total_live,
610    }
611}
612
613/// The groups of `span` with no ancestor in it: the children of the group
614/// before `span`, or the top level for the whole list.
615fn children(groups: &[KeyedGroup], span: Range<usize>) -> impl Iterator<Item = usize> + '_ {
616    let mut next = span.start;
617    std::iter::from_fn(move || {
618        let child = next;
619        (child < span.end).then(|| {
620            next = groups[child].end as usize;
621            child
622        })
623    })
624}
625
626/// The totals of `rows` in one pass, in order: the live rows of a flat
627/// view, or the rows a tree's totals count. Returns the totals' run and the
628/// number of rows. A custom aggregate goes over the rows again.
629pub(super) fn flat_totals<'a, R: GridRow>(
630    aggregates: &ViewAggregates<'_, R>,
631    rows: impl Iterator<Item = &'a R> + Clone,
632) -> (Vec<OwnedValue>, usize) {
633    let mut partials: Vec<Partial<'a>> = aggregates.start().collect();
634    let mut count = 0;
635    for row in rows.clone() {
636        count += 1;
637        aggregates.add(&mut partials, row);
638    }
639    let mut totals = vec![OwnedValue::Empty; aggregates.list.len()];
640    aggregates.finish(&partials, &mut totals);
641    for &(place, function) in &aggregates.custom {
642        let column = aggregates.list[place].0;
643        totals[place] = function.aggregate(column, &mut rows.clone());
644    }
645    (totals, count)
646}
647
648/// The order of a flat or grouped projection with fresh aggregates and row
649/// counts from the rows `snapshot` still has: the aggregate job. The order,
650/// the lines, the expansion and the footers stay; the version is the
651/// snapshot's. Groups combine in key order, as in a rebuild, so the result
652/// is what a rebuild of the same order gives.
653pub(super) fn refresh<R: GridRow>(
654    previous: &Projection,
655    snapshot: &StoreSnapshot<R>,
656    spec: &ViewSpec<R>,
657) -> Projection {
658    let aggregates = ViewAggregates::new(spec);
659    let row = |id: &RowId| snapshot.row(*id).map(|row| &**row);
660    let Some(data) = previous.group_data() else {
661        let (totals, live) = flat_totals(&aggregates, previous.rows().iter().filter_map(row));
662        return previous
663            .duplicate()
664            .with_store_version(snapshot.version())
665            .with_row_count(live)
666            .with_totals(AggregateValues::new(aggregates.columns(), totals));
667    };
668
669    // The groups in key order: the order their key places give.
670    let mut key_order: Vec<usize> = (0..data.groups.len()).collect();
671    key_order.sort_unstable_by_key(|&ix| data.groups[ix].key_ix);
672    let mut keyed: Vec<KeyedGroup> = key_order
673        .iter()
674        .map(|&ix| {
675            let group = &data.groups[ix];
676            KeyedGroup {
677                depth: group.depth(),
678                end: 0,
679                rows: group.rows.clone(),
680            }
681        })
682        .collect();
683    // A group's subgroups follow it in key order too, up to the next group
684    // no deeper than it.
685    let mut open: Vec<usize> = Vec::new();
686    for ix in 0..keyed.len() {
687        while let Some(&top) = open.last()
688            && keyed[top].depth >= keyed[ix].depth
689        {
690            keyed[top].end = ix as u32;
691            open.pop();
692        }
693        open.push(ix);
694    }
695    for top in open {
696        keyed[top].end = keyed.len() as u32;
697    }
698
699    let mut computed = aggregate_groups(&aggregates, &keyed, data.levels, previous.rows(), row);
700    let width = aggregates.columns().len();
701    let mut groups = data.groups.clone();
702    let mut values = vec![OwnedValue::Empty; groups.len() * width];
703    for (key_ix, &ix) in key_order.iter().enumerate() {
704        groups[ix].live = computed.live[key_ix];
705        for (value, computed) in values[ix * width..(ix + 1) * width]
706            .iter_mut()
707            .zip(&mut computed.values[key_ix * width..(key_ix + 1) * width])
708        {
709            *value = mem::replace(computed, OwnedValue::Empty);
710        }
711    }
712    let columns = aggregates.columns();
713    previous.with_group_values(
714        GroupData::new(data.levels, groups, AggregateValues::new(columns, values)),
715        AggregateValues::new(columns, computed.totals),
716        computed.total_live,
717        snapshot.version(),
718    )
719}