From f8acbd5832f661f7ab53628b007d8a431d5b7a7e Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 06:55:26 +0000 Subject: [PATCH] feat(figcraft-format): expose archive compression modes --- crates/figcraft-format/src/lib.rs | 3 +++ crates/zip/src/write.rs | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/crates/figcraft-format/src/lib.rs b/crates/figcraft-format/src/lib.rs index df61cd065..19e5f1175 100644 --- a/crates/figcraft-format/src/lib.rs +++ b/crates/figcraft-format/src/lib.rs @@ -253,3 +253,6 @@ mod streaming_writer_tests { assert_eq!(value["format"], FORMAT); } } + +/// ZIP compression modes for native archive members. +pub use craft_zip::Compression; diff --git a/crates/zip/src/write.rs b/crates/zip/src/write.rs index 12838a3b8..2b32e1e74 100644 --- a/crates/zip/src/write.rs +++ b/crates/zip/src/write.rs @@ -35,7 +35,19 @@ impl Writer { /// Adds an entry from a byte slice. A name the archive already has is an error. pub fn add(&mut self, name: &str, data: &[u8], compression: Compression) -> Result<(), Error> { - self.add_with(name, compression, |writer| writer.write_all(data)) + let (method, level) = match compression { + Compression::Stored => (zip::CompressionMethod::Stored, None), + Compression::Deflated => (zip::CompressionMethod::Deflated, Some(6)), + Compression::Level(l) => (zip::CompressionMethod::Deflated, Some(i64::from(l.min(9)))), + }; + let options = zip::write::SimpleFileOptions::default() + .compression_method(method) + .compression_level(level) + .last_modified_time(zip::DateTime::default()) + .large_file(data.len() as u64 >= u64::from(u32::MAX) / 2); + let fail = |e: &dyn std::fmt::Display| Error::Write(format!("{name}: {e}")); + self.zip.start_file(name, options).map_err(|e| fail(&e))?; + self.zip.write_all(data).map_err(|e| fail(&e)) } /// Adds an entry by streaming it into the compressor, so large generated entries need not @@ -46,8 +58,11 @@ impl Writer { Compression::Deflated => (zip::CompressionMethod::Deflated, Some(6)), Compression::Level(l) => (zip::CompressionMethod::Deflated, Some(i64::from(l.min(9)))), }; - let options = - zip::write::SimpleFileOptions::default().compression_method(method).compression_level(level).last_modified_time(zip::DateTime::default()); + let options = zip::write::SimpleFileOptions::default() + .compression_method(method) + .compression_level(level) + .last_modified_time(zip::DateTime::default()) + .large_file(true); let fail = |e: &dyn std::fmt::Display| Error::Write(format!("{name}: {e}")); self.zip.start_file(name, options).map_err(|e| fail(&e))?; write(&mut self.zip).map_err(|e| fail(&e))