@@ -478,25 +478,71 @@ pub unsafe extern "C-unwind" fn uncompress(
478478 dest : * mut u8 ,
479479 destLen : * mut c_ulong ,
480480 source : * const u8 ,
481- sourceLen : c_ulong ,
481+ mut sourceLen : c_ulong ,
482+ ) -> c_int {
483+ uncompress2 ( dest, destLen, source, & mut sourceLen)
484+ }
485+
486+ /// Inflates `source` into `dest` like [`uncompress`], and writes the final inflated size into `destLen` and the number
487+ /// of source bytes consumed into `sourceLen`.
488+ ///
489+ /// Upon entry, `destLen` is the total size of the destination buffer, which must be large enough to hold the entire
490+ /// uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and
491+ /// transmitted to the decompressor by some mechanism outside the scope of this compression library.)
492+ /// Upon exit, `destLen` is the actual size of the uncompressed data.
493+ ///
494+ /// # Returns
495+ ///
496+ /// * [`Z_OK`] if success
497+ /// * [`Z_MEM_ERROR`] if there was not enough memory
498+ /// * [`Z_BUF_ERROR`] if there was not enough room in the output buffer
499+ /// * [`Z_DATA_ERROR`] if the input data was corrupted or incomplete
500+ ///
501+ /// In the case where there is not enough room, [`uncompress2`] will fill the output buffer with the uncompressed data up to that point.
502+ ///
503+ /// # Safety
504+ ///
505+ /// The caller must guarantee that
506+ ///
507+ /// * Either
508+ /// - `destLen` is `NULL`
509+ /// - `destLen` satisfies the requirements of `&mut *destLen`
510+ /// * Either
511+ /// - `dest` is `NULL`
512+ /// - `dest` and `*destLen` satisfy the requirements of [`core::slice::from_raw_parts_mut::<MaybeUninit<u8>>`]
513+ /// * Either
514+ /// - `source` is `NULL`
515+ /// - `source` and `sourceLen` satisfy the requirements of [`core::slice::from_raw_parts::<u8>`]
516+ /// * `sourceLen` satisfies the requirements of `&mut *sourceLen`
517+ #[ cfg_attr( feature = "export-symbols" , export_name = prefix!( uncompress2) ) ]
518+ pub unsafe extern "C" fn uncompress2 (
519+ dest : * mut u8 ,
520+ destLen : * mut c_ulong ,
521+ source : * const u8 ,
522+ sourceLen : * mut c_ulong ,
482523) -> c_int {
483524 // stock zlib will just dereference a NULL pointer: that's UB.
484525 // Hence us returning an error value is compatible
485526 let Some ( destLen) = ( unsafe { destLen. as_mut ( ) } ) else {
486527 return ReturnCode :: StreamError as _ ;
487528 } ;
488529
530+ let Some ( sourceLen) = ( unsafe { sourceLen. as_mut ( ) } ) else {
531+ return ReturnCode :: StreamError as _ ;
532+ } ;
533+
489534 let Some ( output) = ( unsafe { slice_from_raw_parts_uninit_mut ( dest, * destLen as usize ) } ) else {
490535 return ReturnCode :: StreamError as _ ;
491536 } ;
492537
493- let Some ( input) = ( unsafe { slice_from_raw_parts ( source, sourceLen as usize ) } ) else {
538+ let Some ( input) = ( unsafe { slice_from_raw_parts ( source, * sourceLen as usize ) } ) else {
494539 return ReturnCode :: StreamError as _ ;
495540 } ;
496541
497542 let config = InflateConfig :: default ( ) ;
498- let ( output, err) = zlib_rs:: inflate:: uncompress ( output, input, config) ;
543+ let ( consumed , output, err) = zlib_rs:: inflate:: uncompress2 ( output, input, config) ;
499544
545+ * sourceLen -= consumed as c_ulong ;
500546 * destLen = output. len ( ) as c_ulong ;
501547
502548 err as c_int
0 commit comments