use std::collections::{BTreeMap, BTreeSet};
use icu_casemap::CaseMapperBorrowed;
use crate::address::Address;
use crate::casefold::simple_fold;
use crate::depgraph::CellRef;
use crate::spill::{spill_rect, SpillRect};
use crate::value::Value;
use crate::workbook::Workbook;
#[derive(Debug, Default)]
pub(crate) struct GridSpillIndex {
by_sheet: BTreeMap<String, Vec<(Address, SpillRect)>>,
}
impl GridSpillIndex {
pub(crate) fn build(workbook: &Workbook, recomputed: &BTreeSet<CellRef>) -> Self {
let folder = CaseMapperBorrowed::new();
let mut by_sheet: BTreeMap<String, Vec<(Address, SpillRect)>> = BTreeMap::new();
for sheet in workbook.sheets() {
let folded = simple_fold(&folder, sheet.name());
let mut anchors: Vec<(Address, SpillRect)> = Vec::new();
for (addr, cell) in sheet.iter() {
let Value::Array(rows) = cell.value() else {
continue;
};
let nrows = rows.len();
let ncols = rows.first().map_or(0, Vec::len);
let Some(rect) = spill_rect(addr, nrows, ncols) else {
continue; };
let anchor = CellRef {
sheet: folded.clone(),
addr,
};
if recomputed.contains(&anchor) {
continue;
}
anchors.push((addr, rect));
}
if !anchors.is_empty() {
by_sheet.insert(folded, anchors);
}
}
Self { by_sheet }
}
pub(crate) fn anchors(&self, sheet_folded: &str) -> &[(Address, SpillRect)] {
self.by_sheet.get(sheet_folded).map_or(&[], Vec::as_slice)
}
}
#[cfg(test)]
mod tests;