Skip to content

Commit 3cae7da

Browse files
authored
Merge pull request #502 from NobodyXu/patch-1
Add `(de)compress_uninit` that accepts `&[MaybeUninit<u8>]`
2 parents b9afa93 + ee3d877 commit 3cae7da

File tree

3 files changed

+183
-83
lines changed

3 files changed

+183
-83
lines changed

src/ffi/c.rs

Lines changed: 102 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Implementation for C backends.
2-
use std::cmp;
32
use std::fmt;
43
use std::marker;
4+
use std::mem::MaybeUninit;
55
use std::os::raw::{c_int, c_uint};
66
use std::ptr;
77

@@ -226,34 +226,12 @@ pub struct Inflate {
226226
pub inner: Stream<DirDecompress>,
227227
}
228228

229-
impl InflateBackend for Inflate {
230-
fn make(zlib_header: bool, window_bits: u8) -> Self {
231-
unsafe {
232-
let state = StreamWrapper::default();
233-
let ret = mz_inflateInit2(
234-
state.inner,
235-
if zlib_header {
236-
window_bits as c_int
237-
} else {
238-
-(window_bits as c_int)
239-
},
240-
);
241-
assert_eq!(ret, 0);
242-
Inflate {
243-
inner: Stream {
244-
stream_wrapper: state,
245-
total_in: 0,
246-
total_out: 0,
247-
_marker: marker::PhantomData,
248-
},
249-
}
250-
}
251-
}
252-
253-
fn decompress(
229+
impl Inflate {
230+
unsafe fn decompress_inner(
254231
&mut self,
255232
input: &[u8],
256-
output: &mut [u8],
233+
output_ptr: *mut u8,
234+
output_len: usize,
257235
flush: FlushDecompress,
258236
) -> Result<Status, DecompressError> {
259237
let raw = self.inner.stream_wrapper.inner;
@@ -263,16 +241,16 @@ impl InflateBackend for Inflate {
263241
unsafe {
264242
(*raw).msg = ptr::null_mut();
265243
(*raw).next_in = input.as_ptr() as *mut u8;
266-
(*raw).avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint;
267-
(*raw).next_out = output.as_mut_ptr();
268-
(*raw).avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint;
244+
(*raw).avail_in = input.len().min(c_uint::MAX as usize) as c_uint;
245+
(*raw).next_out = output_ptr;
246+
(*raw).avail_out = output_len.min(c_uint::MAX as usize) as c_uint;
269247

270248
let rc = mz_inflate(raw, flush as c_int);
271249

272250
// Unfortunately the total counters provided by zlib might be only
273251
// 32 bits wide and overflow while processing large amounts of data.
274252
self.inner.total_in += ((*raw).next_in as usize - input.as_ptr() as usize) as u64;
275-
self.inner.total_out += ((*raw).next_out as usize - output.as_ptr() as usize) as u64;
253+
self.inner.total_out += ((*raw).next_out as usize - output_ptr as usize) as u64;
276254

277255
// reset these pointers so we don't accidentally read them later
278256
(*raw).next_in = ptr::null_mut();
@@ -293,6 +271,47 @@ impl InflateBackend for Inflate {
293271
}
294272
}
295273
}
274+
}
275+
impl InflateBackend for Inflate {
276+
fn make(zlib_header: bool, window_bits: u8) -> Self {
277+
unsafe {
278+
let state = StreamWrapper::default();
279+
let ret = mz_inflateInit2(
280+
state.inner,
281+
if zlib_header {
282+
window_bits as c_int
283+
} else {
284+
-(window_bits as c_int)
285+
},
286+
);
287+
assert_eq!(ret, 0);
288+
Inflate {
289+
inner: Stream {
290+
stream_wrapper: state,
291+
total_in: 0,
292+
total_out: 0,
293+
_marker: marker::PhantomData,
294+
},
295+
}
296+
}
297+
}
298+
299+
fn decompress(
300+
&mut self,
301+
input: &[u8],
302+
output: &mut [u8],
303+
flush: FlushDecompress,
304+
) -> Result<Status, DecompressError> {
305+
unsafe { self.decompress_inner(input, output.as_mut_ptr(), output.len(), flush) }
306+
}
307+
fn decompress_uninit(
308+
&mut self,
309+
input: &[u8],
310+
output: &mut [MaybeUninit<u8>],
311+
flush: FlushDecompress,
312+
) -> Result<Status, DecompressError> {
313+
unsafe { self.decompress_inner(input, output.as_mut_ptr() as *mut _, output.len(), flush) }
314+
}
296315

297316
fn reset(&mut self, zlib_header: bool) {
298317
let bits = if zlib_header {
@@ -325,37 +344,12 @@ pub struct Deflate {
325344
pub inner: Stream<DirCompress>,
326345
}
327346

328-
impl DeflateBackend for Deflate {
329-
fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self {
330-
unsafe {
331-
let state = StreamWrapper::default();
332-
let ret = mz_deflateInit2(
333-
state.inner,
334-
level.0 as c_int,
335-
MZ_DEFLATED,
336-
if zlib_header {
337-
window_bits as c_int
338-
} else {
339-
-(window_bits as c_int)
340-
},
341-
8,
342-
MZ_DEFAULT_STRATEGY,
343-
);
344-
assert_eq!(ret, 0);
345-
Deflate {
346-
inner: Stream {
347-
stream_wrapper: state,
348-
total_in: 0,
349-
total_out: 0,
350-
_marker: marker::PhantomData,
351-
},
352-
}
353-
}
354-
}
355-
fn compress(
347+
impl Deflate {
348+
unsafe fn compress_inner(
356349
&mut self,
357350
input: &[u8],
358-
output: &mut [u8],
351+
output_ptr: *mut u8,
352+
output_len: usize,
359353
flush: FlushCompress,
360354
) -> Result<Status, CompressError> {
361355
let raw = self.inner.stream_wrapper.inner;
@@ -365,17 +359,17 @@ impl DeflateBackend for Deflate {
365359
unsafe {
366360
(*raw).msg = ptr::null_mut();
367361
(*raw).next_in = input.as_ptr() as *mut _;
368-
(*raw).avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint;
369-
(*raw).next_out = output.as_mut_ptr();
370-
(*raw).avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint;
362+
(*raw).avail_in = input.len().min(c_uint::MAX as usize) as c_uint;
363+
(*raw).next_out = output_ptr;
364+
(*raw).avail_out = output_len.min(c_uint::MAX as usize) as c_uint;
371365

372366
let rc = mz_deflate(raw, flush as c_int);
373367

374368
// Unfortunately the total counters provided by zlib might be only
375369
// 32 bits wide and overflow while processing large amounts of data.
376370

377371
self.inner.total_in += ((*raw).next_in as usize - input.as_ptr() as usize) as u64;
378-
self.inner.total_out += ((*raw).next_out as usize - output.as_ptr() as usize) as u64;
372+
self.inner.total_out += ((*raw).next_out as usize - output_ptr as usize) as u64;
379373
// reset these pointers so we don't accidentally read them later
380374
(*raw).next_in = ptr::null_mut();
381375
(*raw).avail_in = 0;
@@ -391,7 +385,51 @@ impl DeflateBackend for Deflate {
391385
}
392386
}
393387
}
388+
}
394389

390+
impl DeflateBackend for Deflate {
391+
fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self {
392+
unsafe {
393+
let state = StreamWrapper::default();
394+
let ret = mz_deflateInit2(
395+
state.inner,
396+
level.0 as c_int,
397+
MZ_DEFLATED,
398+
if zlib_header {
399+
window_bits as c_int
400+
} else {
401+
-(window_bits as c_int)
402+
},
403+
8,
404+
MZ_DEFAULT_STRATEGY,
405+
);
406+
assert_eq!(ret, 0);
407+
Deflate {
408+
inner: Stream {
409+
stream_wrapper: state,
410+
total_in: 0,
411+
total_out: 0,
412+
_marker: marker::PhantomData,
413+
},
414+
}
415+
}
416+
}
417+
fn compress(
418+
&mut self,
419+
input: &[u8],
420+
output: &mut [u8],
421+
flush: FlushCompress,
422+
) -> Result<Status, CompressError> {
423+
unsafe { self.compress_inner(input, output.as_mut_ptr(), output.len(), flush) }
424+
}
425+
fn compress_uninit(
426+
&mut self,
427+
input: &[u8],
428+
output: &mut [MaybeUninit<u8>],
429+
flush: FlushCompress,
430+
) -> Result<Status, CompressError> {
431+
unsafe { self.compress_inner(input, output.as_mut_ptr() as *mut _, output.len(), flush) }
432+
}
395433
fn reset(&mut self) {
396434
self.inner.total_in = 0;
397435
self.inner.total_out = 0;

src/ffi/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
33
use crate::mem::{CompressError, DecompressError, FlushCompress, FlushDecompress, Status};
44
use crate::Compression;
5+
use std::mem::MaybeUninit;
6+
7+
fn initialize_buffer(output: &mut [MaybeUninit<u8>]) -> &mut [u8] {
8+
// SAFETY: Here we zero-initialize the output and cast it to [u8]
9+
unsafe {
10+
output.as_mut_ptr().write_bytes(0, output.len());
11+
&mut *(output as *mut [MaybeUninit<u8>] as *mut [u8])
12+
}
13+
}
514

615
/// Traits specifying the interface of the backends.
716
///
@@ -20,6 +29,14 @@ pub trait InflateBackend: Backend {
2029
output: &mut [u8],
2130
flush: FlushDecompress,
2231
) -> Result<Status, DecompressError>;
32+
fn decompress_uninit(
33+
&mut self,
34+
input: &[u8],
35+
output: &mut [MaybeUninit<u8>],
36+
flush: FlushDecompress,
37+
) -> Result<Status, DecompressError> {
38+
self.decompress(input, initialize_buffer(output), flush)
39+
}
2340
fn reset(&mut self, zlib_header: bool);
2441
}
2542

@@ -31,6 +48,14 @@ pub trait DeflateBackend: Backend {
3148
output: &mut [u8],
3249
flush: FlushCompress,
3350
) -> Result<Status, CompressError>;
51+
fn compress_uninit(
52+
&mut self,
53+
input: &[u8],
54+
output: &mut [MaybeUninit<u8>],
55+
flush: FlushCompress,
56+
) -> Result<Status, CompressError> {
57+
self.compress(input, initialize_buffer(output), flush)
58+
}
3459
fn reset(&mut self);
3560
}
3661

0 commit comments

Comments
 (0)