diff --git a/crates/xlsx/src/tests/shared_media.rs b/crates/xlsx/src/tests/shared_media.rs index a1d7bc0c7..0c37e584b 100644 --- a/crates/xlsx/src/tests/shared_media.rs +++ b/crates/xlsx/src/tests/shared_media.rs @@ -85,3 +85,21 @@ fn different_pictures_with_the_same_length_stay_separate() { let back = read_xlsx(&bytes).unwrap().0; assert_eq!(back.sheets[0].images.iter().map(|i| i.data.to_vec()).collect::>(), vec![a, b]); } + +/// Many distinct pictures that share a long prefix: each is matched against the earlier ones +/// through a content hash, not by comparing bytes with every one of them. +#[test] +fn many_distinct_pictures_with_a_common_prefix_are_each_written_once() { + let pictures: Vec> = (0..400u32) + .map(|i| { + let mut v = b"\x89PNG\r\n\x1a\n".to_vec(); + v.extend(std::iter::repeat_n(7u8, 65_536)); + v.extend(i.to_le_bytes()); + v + }) + .collect(); + let refs: Vec<(u32, &[u8])> = pictures.iter().enumerate().map(|(i, p)| (i as u32 + 1, p.as_slice())).collect(); + let wb = Workbook { sheets: vec![sheet_with("One", &refs), sheet_with("Two", &refs)], ..Default::default() }; + let bytes = write_xlsx(&wb).unwrap(); + assert_eq!(names(&bytes).iter().filter(|n| n.starts_with("xl/media/")).count(), 400); +} diff --git a/crates/xlsx/src/write.rs b/crates/xlsx/src/write.rs index 512144980..8f8c57105 100644 --- a/crates/xlsx/src/write.rs +++ b/crates/xlsx/src/write.rs @@ -6,6 +6,7 @@ use std::fmt::Write as _; use gridcraft_core::RangeRef; use gridcraft_formula::quote_sheet; use gridcraft_model::{CalcMode, CalcSettings, PhoneticString, ShowObjects, Style, Visibility, Workbook, WorkbookView}; +use sha2::Digest as _; use crate::package::ZipOut; use crate::xml::{esc, esc_attr}; @@ -112,6 +113,9 @@ pub struct Out { pub dxfs: Vec