|
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