Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions libz-rs-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,13 @@ pub unsafe extern "C" fn inflate(strm: *mut z_stream, flush: i32) -> i32 {
}

pub unsafe extern "C" fn inflateEnd(strm: *mut z_stream) -> i32 {
zlib_rs::inflate::end(strm)
match InflateStream::from_stream_mut(strm) {
Some(stream) => {
zlib_rs::inflate::end(stream);
ReturnCode::Ok as _
}
None => ReturnCode::StreamError as _,
}
}

pub unsafe extern "C" fn inflateBackInit_(
Expand Down Expand Up @@ -117,8 +123,12 @@ pub unsafe extern "C" fn inflateBackEnd(_strm: z_streamp) -> c_int {
}

pub unsafe extern "C" fn inflateCopy(dest: *mut z_stream, source: *const z_stream) -> i32 {
if dest.is_null() {
return ReturnCode::StreamError as _;
}

if let Some(source) = InflateStream::from_stream_ref(source) {
zlib_rs::inflate::copy(dest, source) as _
zlib_rs::inflate::copy(&mut *(dest as *mut MaybeUninit<InflateStream>), source) as _
} else {
ReturnCode::StreamError as _
}
Expand Down Expand Up @@ -338,7 +348,10 @@ pub extern "C" fn compressBound(sourceLen: c_ulong) -> c_ulong {

pub unsafe extern "C" fn deflateEnd(strm: *mut z_stream) -> i32 {
match DeflateStream::from_stream_mut(strm) {
Some(stream) => zlib_rs::deflate::end(stream) as _,
Some(stream) => match zlib_rs::deflate::end(stream) {
Ok(_) => ReturnCode::Ok as _,
Err(_) => ReturnCode::DataError as _,
},
None => ReturnCode::StreamError as _,
}
}
Expand Down Expand Up @@ -404,6 +417,19 @@ pub unsafe extern "C" fn deflatePending(
}
}

pub unsafe extern "C" fn deflateCopy(dest: z_streamp, source: z_streamp) -> c_int {
let dest = if dest.is_null() {
return ReturnCode::StreamError as _;
} else {
&mut *(dest as *mut MaybeUninit<_>)
};

match DeflateStream::from_stream_mut(source) {
Some(source) => zlib_rs::deflate::copy(dest, source) as _,
None => ReturnCode::StreamError as _,
}
}

pub unsafe extern "C" fn deflateInit_(
strm: z_streamp,
level: c_int,
Expand Down
64 changes: 64 additions & 0 deletions libz-rs-sys/src/tests/deflate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,3 +1436,67 @@ fn test_deflate_hash_head_0() {

assert_eq!(uncompressed, next_in);
}

#[test]
fn test_deflate_copy() {
const HELLO: &str = "hello, hello!\0";

let config = DeflateConfig::default();

let mut strm = MaybeUninit::zeroed();

unsafe {
// first validate the config
let err = libz_rs_sys::deflateInit2_(
strm.as_mut_ptr(),
config.level,
config.method as i32,
config.window_bits,
config.mem_level,
config.strategy as i32,
VERSION,
STREAM_SIZE,
);
assert_eq!(err, 0);

let strm = strm.assume_init_mut();

let mut compr = [0; 32];
strm.next_in = HELLO.as_ptr() as *mut u8;
strm.next_out = compr.as_mut_ptr();

for _ in HELLO.as_bytes() {
strm.avail_in = 1;
strm.avail_out = 1;

let err = libz_rs_sys::deflate(strm, Flush::NoFlush as i32);
assert_eq!(err, 0);
}

loop {
strm.avail_out = 1;
let err = libz_rs_sys::deflate(strm, Flush::Finish as i32);

if ReturnCode::from(err) == ReturnCode::StreamEnd {
break;
}

assert_eq!(err, 0);
}

let mut copy = MaybeUninit::uninit();
let err = libz_rs_sys::deflateCopy(copy.as_mut_ptr(), strm);
assert_eq!(err, 0);

assert_eq!(
*(strm.state as *const u8),
*(((*copy.as_mut_ptr()).state) as *const u8),
);

let err = libz_rs_sys::deflateEnd(strm);
assert_eq!(err, 0);

let err = libz_rs_sys::deflateEnd(copy.as_mut_ptr());
assert_eq!(err, 0);
}
}
46 changes: 45 additions & 1 deletion zlib-rs/src/allocate.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use std::ffi::{c_uint, c_void};
use std::{
alloc::Layout,
ffi::{c_uint, c_void},
marker::PhantomData,
mem::MaybeUninit,
};

use libc::size_t;

Expand Down Expand Up @@ -63,3 +68,42 @@ unsafe fn zng_free(ptr: *mut c_void) {
// TODO based on the zlig-ng code this may need to use _aligned_free on (32-bit?) windows
unsafe { libc::free(ptr) };
}

#[derive(Clone, Copy)]
#[repr(C)]
pub(crate) struct Allocator<'a> {
pub(crate) zalloc: crate::c_api::alloc_func,
pub(crate) zfree: crate::c_api::free_func,
pub(crate) opaque: crate::c_api::voidpf,
pub(crate) _marker: PhantomData<&'a ()>,
}

impl<'a> Allocator<'a> {
pub fn allocate<T>(&self) -> Option<&'a mut MaybeUninit<T>> {
let layout = Layout::new::<T>();
let ptr = unsafe { (self.zalloc)(self.opaque, layout.size() as _, 1) };

if ptr.is_null() {
None
} else {
Some(unsafe { &mut *(ptr as *mut MaybeUninit<T>) })
}
}

pub fn allocate_slice<T>(&self, len: usize) -> Option<&'a mut [MaybeUninit<T>]> {
let layout = Layout::array::<T>(len).ok()?;
let ptr = unsafe { (self.zalloc)(self.opaque, layout.size() as _, 1) };

if ptr.is_null() {
None
} else {
Some(unsafe { core::slice::from_raw_parts_mut(ptr.cast(), len) })
}
}

pub unsafe fn deallocate<T>(&self, ptr: *mut T, _len: usize) {
if !ptr.is_null() {
(self.zfree)(self.opaque, ptr.cast())
}
}
}
29 changes: 2 additions & 27 deletions zlib-rs/src/c_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
use std::ffi::{c_char, c_int, c_uchar, c_uint, c_ulong, c_void};

pub type alloc_func = unsafe extern "C" fn(voidpf, uInt, uInt) -> voidpf;
pub type Bytef = u8;
pub type free_func = unsafe extern "C" fn(voidpf, voidpf);

pub type Bytef = u8;
pub type in_func = unsafe extern "C" fn(*mut c_void, *mut *const c_uchar) -> c_uint;
pub type out_func = unsafe extern "C" fn(*mut c_void, *mut c_uchar, c_uint) -> c_int;
pub type uInt = c_uint;
Expand Down Expand Up @@ -56,32 +57,6 @@ impl Default for z_stream {
}
}

impl z_stream {
pub(crate) unsafe fn alloc_layout(&self, layout: std::alloc::Layout) -> *mut c_void {
match self.zalloc {
None => unreachable!("zalloc no initialized"),
Some(f) => f(self.opaque, 1, layout.size() as u32),
}
}

pub(crate) unsafe fn alloc_value<T>(&self, value: T) -> *mut T {
let ptr = self.alloc_layout(std::alloc::Layout::new::<T>()).cast();

if ptr as usize != 0 {
std::ptr::write(ptr, value);
}

ptr
}

pub(crate) unsafe fn dealloc<T>(&self, ptr: *mut T) {
match self.zfree {
None => unreachable!("zfree no initialized"),
Some(f) => f(self.opaque, ptr.cast()),
}
}
}

// // zlib stores Adler-32 and CRC-32 checksums in unsigned long; zlib-ng uses uint32_t.
pub(crate) type z_size = c_ulong;
pub(crate) type z_checksum = c_ulong;
Expand Down
Loading