diff --git a/crates/engine/src/cmd/slices.rs b/crates/engine/src/cmd/slices.rs index cad1335c1..1adc147c5 100644 --- a/crates/engine/src/cmd/slices.rs +++ b/crates/engine/src/cmd/slices.rs @@ -348,8 +348,13 @@ fn from_guides(s: &mut Session, _: &Value) -> Result { v }; let (xs, ys) = (cuts(true, region.x0, region.x1), cuts(false, region.y0, region.y1)); - let rects: Vec = - ys.windows(2).flat_map(|y| xs.windows(2).map(move |x| Rect::new(x[0], y[0], x[1], y[1]))).filter(|r| valid_rect(*r)).collect(); + // One past the limit tells too many, without making every piece of a huge grid first. + let rects: Vec = ys + .windows(2) + .flat_map(|y| xs.windows(2).map(move |x| Rect::new(x[0], y[0], x[1], y[1]))) + .filter(|r| valid_rect(*r)) + .take(MAX_PIECES + 1) + .collect(); if rects.len() > MAX_PIECES { return Err(EngineError::Other(format!("Create from Guides: the guides make more than {MAX_PIECES} slices"))); } diff --git a/crates/engine/src/tests/slices.rs b/crates/engine/src/tests/slices.rs index f14e878d3..eee1a4769 100644 --- a/crates/engine/src/tests/slices.rs +++ b/crates/engine/src/tests/slices.rs @@ -86,6 +86,19 @@ fn releasing_a_user_slice_leaves_an_unpainted_rectangle() { assert_eq!(s.doc().unwrap().selection.objects, vec![NodeId(rid)]); } +/// Guides cutting more pieces than a document takes are refused before the grid is made. +#[test] +fn too_many_guide_pieces_are_refused() { + let mut s = session(); + let doc = std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc); + for i in 1..3000 { + for vertical in [true, false] { + doc.guides.push(vectorcraft_doc::Guide::new(vertical, f64::from(i) * 0.1)); + } + } + assert!(s.execute("object.slice.fromGuides", &json!({})).unwrap_err().to_string().contains("more than")); +} + #[test] fn guides_give_nine_slices() { let mut s = session();