mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-31 14:07:06 -06:00
Model: an exhausted id space refuses growth instead of duplicating ids (#407)
alloc_id bumped next_id with saturating_add: a presentation whose next_id reached u32::MAX (a hostile file can arrive that way; fix_next_id imports it) handed out that same id to every new slide, shape, layout and media - duplicate ids, ambiguous references, silent corruption on every later insert. alloc_id now returns Option<u32> via checked_add, and every caller refuses: the engine's insert/duplicate/media/layout commands answer with a clear error naming the command, paste and duplicate re-id helpers propagate it, media addition is fallible, and a fresh slide is Option. The pptx export's synthesized blank layout is guarded the same way. Loading keeps such a deck viewable: repair re-ids duplicate slides while it can, and a duplicate it cannot re-id stays as it is - growth is refused, and only that duplicate keeps its ambiguous id. Renumbering the loaded graph was rejected: it needs the cross-document reference remapping that issue #406 tracks. Tests: model exhaustion (alloc_id None, fresh media refused, a new slide refused), engine (slide.new, shape.insert, slide.duplicate and edit.duplicate all refuse; the document holds no duplicate ids), format repair (an unre-id-able duplicate stays visible).
This commit is contained in:
@@ -929,7 +929,7 @@ impl Session {
|
||||
let list = cmd::current_shapes(doc, sel).cloned().unwrap_or_default();
|
||||
let mut copies: Vec<Shape> = list.iter().filter(|x| ids.contains(&x.id)).cloned().collect();
|
||||
let boxes: Vec<Xfrm> = copies.iter().map(|c| xfrm_of(doc, sel, c)).collect();
|
||||
cmd::edit::reid(doc, &mut copies);
|
||||
cmd::edit::reid("edit.duplicate", doc, &mut copies)?;
|
||||
for (c, b) in copies.iter_mut().zip(boxes) {
|
||||
c.xfrm = Some(b);
|
||||
c.ph = None;
|
||||
@@ -1049,7 +1049,7 @@ impl Session {
|
||||
let id = match existing {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
let id = ShapeId(doc.alloc_id());
|
||||
let id = ShapeId(doc.alloc_id().ok_or_else(|| cmd::bad("ink.draw", cmd::NO_ID_SPACE))?);
|
||||
let size = doc.slide_size;
|
||||
let list = crate::shapes_mut(doc, sel).ok_or_else(|| cmd::bad("ink", "no slide"))?;
|
||||
list.push(Shape {
|
||||
|
||||
Reference in New Issue
Block a user