mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-06 18:42:15 +00:00
table: refuse to split more than 1024 merged-cell owners at once (#2273)
This commit is contained in:
1 parent
2042bd9698
commit
ae93ea5115
1 file changed
+20
@@ -5,6 +5,9 @@ use super::grid::CellRange;
|
||||
use super::story::append_story;
|
||||
use super::{Story, Table};
|
||||
|
||||
/// Most merged-cell owners one `split_cells` call splits.
|
||||
const MAX_SPLIT_OWNERS: usize = 1024;
|
||||
|
||||
impl Table {
|
||||
/// The smallest range containing `r` that doesn't cut through a merged region.
|
||||
pub fn expand_range(&self, mut r: CellRange) -> CellRange {
|
||||
@@ -78,6 +81,11 @@ impl Table {
|
||||
selected.insert(*owner);
|
||||
}
|
||||
}
|
||||
// Each owner is split by a transformation that rebuilds the grid's ownership: quadratic in the
|
||||
// owners, so a very large selection is refused (a table this size is split in parts).
|
||||
if selected.len() > MAX_SPLIT_OWNERS {
|
||||
return Err(format!("too many cells to split at once (at most {MAX_SPLIT_OWNERS})"));
|
||||
}
|
||||
let mut targets = Vec::new();
|
||||
for (r, c) in selected {
|
||||
let cell = self.cell(r, c).ok_or("missing split cell")?;
|
||||
@@ -232,6 +240,18 @@ impl Table {
|
||||
mod split_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn splitting_a_huge_selection_is_refused() {
|
||||
let mut t = Table::new(1, 40, 40, 0, 0, 400.0);
|
||||
let all = CellRange { r0: 0, c0: 0, r1: 39, c1: 39 };
|
||||
let before = (t.nrows(), t.ncols());
|
||||
assert!(t.split_cells(all, true).unwrap_err().contains("too many cells"));
|
||||
assert_eq!((t.nrows(), t.ncols()), before, "nothing was split");
|
||||
// A selection within the limit still splits.
|
||||
let some = CellRange { r0: 0, c0: 0, r1: 1, c1: 1 };
|
||||
assert!(t.split_cells(some, true).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_single_and_merged_cells() {
|
||||
let mut t = Table::new(1, 2, 2, 0, 0, 100.0);
|
||||
|
||||
Reference in new issue
Block a user