|
1 | 1 | use std::error::Error;
|
2 | 2 | use std::fmt;
|
3 | 3 | use std::io;
|
4 |
| -use std::slice; |
5 | 4 |
|
6 | 5 | use crate::ffi::{self, Backend, Deflate, DeflateBackend, ErrorMessage, Inflate, InflateBackend};
|
7 | 6 | use crate::Compression;
|
@@ -342,19 +341,12 @@ impl Compress {
|
342 | 341 | output: &mut Vec<u8>,
|
343 | 342 | flush: FlushCompress,
|
344 | 343 | ) -> 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| { |
349 | 345 | 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 | + }) |
358 | 350 | }
|
359 | 351 | }
|
360 | 352 |
|
@@ -473,19 +465,12 @@ impl Decompress {
|
473 | 465 | output: &mut Vec<u8>,
|
474 | 466 | flush: FlushDecompress,
|
475 | 467 | ) -> 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| { |
480 | 469 | 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 | + }) |
489 | 474 | }
|
490 | 475 |
|
491 | 476 | /// Specifies the decompression dictionary to use.
|
@@ -574,6 +559,29 @@ impl fmt::Display for CompressError {
|
574 | 559 | }
|
575 | 560 | }
|
576 | 561 |
|
| 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 | + |
577 | 585 | #[cfg(test)]
|
578 | 586 | mod tests {
|
579 | 587 | use std::io::Write;
|
|
0 commit comments