Skip to content

Commit f285e9a

Browse files
authored
Merge pull request #373 from anforowicz/fix-spare-capacity-handling
Fix spare capacity handling
2 parents 20cdcbe + 69972b8 commit f285e9a

File tree

1 file changed

+33
-25
lines changed

1 file changed

+33
-25
lines changed

src/mem.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::error::Error;
22
use std::fmt;
33
use std::io;
4-
use std::slice;
54

65
use crate::ffi::{self, Backend, Deflate, DeflateBackend, ErrorMessage, Inflate, InflateBackend};
76
use crate::Compression;
@@ -342,19 +341,12 @@ impl Compress {
342341
output: &mut Vec<u8>,
343342
flush: FlushCompress,
344343
) -> Result<Status, CompressError> {
345-
let cap = output.capacity();
346-
let len = output.len();
347-
348-
unsafe {
344+
write_to_spare_capacity_of_vec(output, |out| {
349345
let before = self.total_out();
350-
let ret = {
351-
let ptr = output.as_mut_ptr().add(len);
352-
let out = slice::from_raw_parts_mut(ptr, cap - len);
353-
self.compress(input, out, flush)
354-
};
355-
output.set_len((self.total_out() - before) as usize + len);
356-
ret
357-
}
346+
let ret = self.compress(input, out, flush);
347+
let bytes_written = self.total_out() - before;
348+
(bytes_written as usize, ret)
349+
})
358350
}
359351
}
360352

@@ -473,19 +465,12 @@ impl Decompress {
473465
output: &mut Vec<u8>,
474466
flush: FlushDecompress,
475467
) -> Result<Status, DecompressError> {
476-
let cap = output.capacity();
477-
let len = output.len();
478-
479-
unsafe {
468+
write_to_spare_capacity_of_vec(output, |out| {
480469
let before = self.total_out();
481-
let ret = {
482-
let ptr = output.as_mut_ptr().add(len);
483-
let out = slice::from_raw_parts_mut(ptr, cap - len);
484-
self.decompress(input, out, flush)
485-
};
486-
output.set_len((self.total_out() - before) as usize + len);
487-
ret
488-
}
470+
let ret = self.decompress(input, out, flush);
471+
let bytes_written = self.total_out() - before;
472+
(bytes_written as usize, ret)
473+
})
489474
}
490475

491476
/// Specifies the decompression dictionary to use.
@@ -574,6 +559,29 @@ impl fmt::Display for CompressError {
574559
}
575560
}
576561

562+
/// Allows `writer` to write data into the spare capacity of the `output` vector.
563+
/// This will not reallocate the vector provided or attempt to grow it, so space
564+
/// for the `output` must be reserved by the caller before calling this
565+
/// function.
566+
///
567+
/// `writer` needs to return the number of bytes written (and can also return
568+
/// another arbitrary return value).
569+
fn write_to_spare_capacity_of_vec<T>(
570+
output: &mut Vec<u8>,
571+
writer: impl FnOnce(&mut [u8]) -> (usize, T),
572+
) -> T {
573+
let cap = output.capacity();
574+
let len = output.len();
575+
576+
output.resize(output.capacity(), 0);
577+
let (bytes_written, ret) = writer(&mut output[len..]);
578+
579+
let new_len = core::cmp::min(len + bytes_written, cap); // Sanitizes `bytes_written`.
580+
output.resize(new_len, 0 /* unused */);
581+
582+
ret
583+
}
584+
577585
#[cfg(test)]
578586
mod tests {
579587
use std::io::Write;

0 commit comments

Comments
 (0)