From 99dc199bb89d2c0f7dfb6f508169e3cf78280073 Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sat, 17 Oct 2026 13:46:22 +0700 Subject: [PATCH] #656: borrow embedded image bytes and copy only the ones a paint uses --- crates/format/src/fig/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/format/src/fig/mod.rs b/crates/format/src/fig/mod.rs index 091492da..90cdd05d 100644 --- a/crates/format/src/fig/mod.rs +++ b/crates/format/src/fig/mod.rs @@ -66,7 +66,7 @@ pub fn import(bytes: &[u8], name: &str) -> Result<(Document, Vec), Forma let file_name = archive.file_name.as_deref().filter(|n| !n.trim().is_empty()).unwrap_or(name); let (json, mut warnings) = map::to_rest(&msg, file_name); let embedded = embedded_images(&msg); - let images = |r: &str| archive.image(r).or_else(|| embedded.get(r).cloned()); + let images = |r: &str| archive.image(r).or_else(|| embedded.get(r).map(|b| b.to_vec())); let (doc, more) = crate::rest::import(&json, &images)?; warnings.extend(more.into_iter().filter_map(map::adapt_warning)); Ok((doc, warnings)) @@ -100,8 +100,9 @@ fn corrupt(msg: impl Into) -> FormatError { /// Image bytes that travel inside the message, by image hash (lowercase hex): a paint's /// `image.dataBlob` indexes the message's `blobs`. Copies written by plugins and other tools embed /// their images this way, and a bare canvas (what the clipboard carries) has no `images/`. The -/// walk is iterative (no recursion on nested data) and skips blobs larger than [`MAX_IMAGE`]. -fn embedded_images(msg: &Kv) -> BTreeMap> { +/// walk is iterative (no recursion on nested data) and skips blobs larger than [`MAX_IMAGE`]. The +/// bytes stay borrowed from the message; only images a paint asks for are copied. +fn embedded_images<'m>(msg: &'m Kv) -> BTreeMap { let blobs = msg.get("blobs").map(Kv::list).unwrap_or_default(); let mut found = BTreeMap::new(); let mut pending = vec![msg]; @@ -109,7 +110,7 @@ fn embedded_images(msg: &Kv) -> BTreeMap> { match value { Kv::Object(fields) => { if let Some((hash, bytes)) = value.get("image").and_then(|image| embedded_image(image, blobs)) { - found.entry(hash).or_insert_with(|| bytes.to_vec()); + found.entry(hash).or_insert(bytes); } pending.extend(fields.iter().filter(|(name, _)| *name != "blobs").map(|(_, field)| field)); }