Skip to content

Commit 69533f1

Browse files
feat: ZipWriter set_auto_large_file() method to enable large-file data descriptor when necessary (#468)
* better write_data_descriptor #467 * useless * Update src/types.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: n4n5 <[email protected]> * rm underscore * cargo fmt --------- Signed-off-by: n4n5 <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent fadbd48 commit 69533f1

File tree

3 files changed

+38
-17
lines changed

3 files changed

+38
-17
lines changed

src/spec.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,32 +108,32 @@ impl ExtraFieldMagic {
108108
///
109109
/// let mut zip = ZipWriter::new(Cursor::new(Vec::new()));
110110
/// // Writing an extremely large file for this test is faster without compression.
111-
/// let options = SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
112111
///
113112
/// let big_len: usize = (zip::ZIP64_BYTES_THR as usize) + 1;
114113
/// let big_buf = vec![0u8; big_len];
115114
/// {
116-
/// zip.start_file("zero.dat", options)?;
117-
/// // This is too big!
118-
/// let res = zip.write_all(&big_buf[..]).err().unwrap();
119-
/// assert_eq!(res.kind(), io::ErrorKind::Other);
120-
/// let description = format!("{}", &res);
121-
/// assert_eq!(description, "Large file option has not been set");
122-
/// }
123-
/// {
124-
/// // Attempting to write anything further to the same zip will still succeed, but the previous
125-
/// // failing entry has been removed.
126-
/// zip.start_file("one.dat", options)?;
127-
/// let zip = zip.finish_into_readable()?;
128-
/// let names: Vec<_> = zip.file_names().collect();
129-
/// assert_eq!(&names, &["one.dat"]);
115+
/// let options = SimpleFileOptions::default()
116+
/// .compression_method(zip::CompressionMethod::Stored);
117+
/// zip.start_file("zero.dat", options)?;
118+
/// // This is too big!
119+
/// let res = zip.write_all(&big_buf[..]).err().unwrap();
120+
/// assert_eq!(res.kind(), io::ErrorKind::Other);
121+
/// let description = format!("{}", &res);
122+
/// assert_eq!(description, "Large file option has not been set");
123+
/// // Attempting to write anything further to the same zip will still succeed, but the previous
124+
/// // failing entry has been removed.
125+
/// zip.start_file("one.dat", options)?;
126+
/// let zip = zip.finish_into_readable()?;
127+
/// let names: Vec<_> = zip.file_names().collect();
128+
/// assert_eq!(&names, &["one.dat"]);
130129
/// }
131130
///
132131
/// // Create a new zip output.
133132
/// let mut zip = ZipWriter::new(Cursor::new(Vec::new()));
134133
/// // This time, create a zip64 record for the file.
135134
/// let options = SimpleFileOptions::default()
136-
/// .compression_method(zip::CompressionMethod::Stored).large_file(true);
135+
/// .compression_method(zip::CompressionMethod::Stored)
136+
/// .large_file(true);
137137
/// zip.start_file("zero.dat", options)?;
138138
/// // This succeeds because we specified that it could be a large file.
139139
/// assert!(zip.write_all(&big_buf[..]).is_ok());

src/types.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,10 +959,21 @@ impl ZipFileData {
959959
pub(crate) fn write_data_descriptor<W: std::io::Write>(
960960
&self,
961961
writer: &mut W,
962+
auto_large_file: bool,
962963
) -> Result<(), ZipError> {
963964
if self.large_file {
964965
return self.zip64_data_descriptor_block().write(writer);
965966
}
967+
if self.compressed_size > spec::ZIP64_BYTES_THR
968+
|| self.uncompressed_size > spec::ZIP64_BYTES_THR
969+
{
970+
if auto_large_file {
971+
return self.zip64_data_descriptor_block().write(writer);
972+
}
973+
return Err(ZipError::Io(std::io::Error::other(
974+
"Large file option has not been set - use .large_file(true) in options",
975+
)));
976+
}
966977
self.data_descriptor_block().write(writer)
967978
}
968979

src/write.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ pub(crate) mod zip_writer {
172172
pub(super) zip64_comment: Option<Box<[u8]>>,
173173
pub(super) flush_on_finish_file: bool,
174174
pub(super) seek_possible: bool,
175+
pub(crate) auto_large_file: bool,
175176
}
176177

177178
impl<W: Write + Seek> Debug for ZipWriter<W> {
@@ -650,6 +651,7 @@ impl<A: Read + Write + Seek> ZipWriter<A> {
650651
writing_raw: true, // avoid recomputing the last file's header
651652
flush_on_finish_file: false,
652653
seek_possible: true,
654+
auto_large_file: false,
653655
})
654656
}
655657

@@ -808,9 +810,16 @@ impl<W: Write + Seek> ZipWriter<W> {
808810
zip64_comment: None,
809811
flush_on_finish_file: false,
810812
seek_possible: true,
813+
auto_large_file: false,
811814
}
812815
}
813816

817+
/// Set automatically large file to true if needed
818+
pub fn set_auto_large_file(mut self) -> Self {
819+
self.auto_large_file = true;
820+
self
821+
}
822+
814823
/// Returns true if a file is currently open for writing.
815824
pub const fn is_writing_file(&self) -> bool {
816825
self.writing_to_file && !self.inner.is_closed()
@@ -1111,7 +1120,7 @@ impl<W: Write + Seek> ZipWriter<W> {
11111120
};
11121121
update_aes_extra_data(writer, file)?;
11131122
if file.using_data_descriptor {
1114-
file.write_data_descriptor(writer)?;
1123+
file.write_data_descriptor(writer, self.auto_large_file)?;
11151124
} else {
11161125
update_local_file_header(writer, file)?;
11171126
writer.seek(SeekFrom::Start(file_end))?;
@@ -1658,6 +1667,7 @@ impl<W: Write> ZipWriter<StreamWriter<W>> {
16581667
zip64_comment: None,
16591668
flush_on_finish_file: false,
16601669
seek_possible: false,
1670+
auto_large_file: false,
16611671
}
16621672
}
16631673
}

0 commit comments

Comments
 (0)