Skip to content

Commit e9232c7

Browse files
committed
add zlib-rs support via the libz-rs-sys C api for zlib-rs
1 parent ae78497 commit e9232c7

File tree

3 files changed

+90
-57
lines changed

3 files changed

+90
-57
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ jobs:
4343
if: matrix.build != 'mingw'
4444
- run: cargo test --features zlib-ng --no-default-features
4545
if: matrix.build != 'mingw'
46+
- run: cargo test --features zlib-rs --no-default-features
47+
if: matrix.build != 'mingw'
4648
- run: cargo test --features cloudflare_zlib --no-default-features
4749
if: matrix.build != 'mingw'
4850
- run: |

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and raw deflate streams.
1919
[dependencies]
2020
libz-sys = { version = "1.1.8", optional = true, default-features = false }
2121
libz-ng-sys = { version = "1.1.8", optional = true }
22+
libz-rs-sys = { version = "0.1.0", optional = true, default-features = false, features = ["std", "rust-allocator"] }
2223
cloudflare-zlib-sys = { version = "0.3.0", optional = true }
2324
miniz_oxide = { version = "0.7.1", optional = true, default-features = false, features = ["with-alloc"] }
2425
crc32fast = "1.2.0"
@@ -38,6 +39,7 @@ zlib = ["any_zlib", "libz-sys"]
3839
zlib-default = ["any_zlib", "libz-sys/default"]
3940
zlib-ng-compat = ["zlib", "libz-sys/zlib-ng"]
4041
zlib-ng = ["any_zlib", "libz-ng-sys"]
42+
zlib-rs = ["any_zlib", "libz-rs-sys"]
4143
cloudflare_zlib = ["any_zlib", "cloudflare-zlib-sys"]
4244
rust_backend = ["miniz_oxide", "any_impl"]
4345
miniz-sys = ["rust_backend"] # For backwards compatibility

src/ffi/c.rs

Lines changed: 86 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
//! Implementation for C backends.
2-
use std::alloc::{self, Layout};
32
use std::cmp;
4-
use std::convert::TryFrom;
53
use std::fmt;
64
use std::marker;
7-
use std::os::raw::{c_int, c_uint, c_void};
5+
use std::os::raw::{c_int, c_uint};
86
use std::ptr;
97

108
use super::*;
@@ -52,14 +50,28 @@ impl Default for StreamWrapper {
5250
reserved: 0,
5351
opaque: ptr::null_mut(),
5452
state: ptr::null_mut(),
55-
#[cfg(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys")))]
56-
zalloc,
57-
#[cfg(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys")))]
58-
zfree,
59-
#[cfg(not(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys"))))]
60-
zalloc: Some(zalloc),
61-
#[cfg(not(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys"))))]
62-
zfree: Some(zfree),
53+
#[cfg(all(
54+
feature = "any_zlib",
55+
not(any(feature = "cloudflare-zlib-sys", feature = "libz-rs-sys"))
56+
))]
57+
zalloc: allocator::zalloc,
58+
#[cfg(all(
59+
feature = "any_zlib",
60+
not(any(feature = "cloudflare-zlib-sys", feature = "libz-rs-sys"))
61+
))]
62+
zfree: allocator::zfree,
63+
64+
#[cfg(all(feature = "any_zlib", feature = "cloudflare-zlib-sys"))]
65+
zalloc: Some(allocator::zalloc),
66+
#[cfg(all(feature = "any_zlib", feature = "cloudflare-zlib-sys"))]
67+
zfree: Some(allocator::zfree),
68+
69+
// for zlib-rs, it is most efficient to have it provide the allocator.
70+
// The libz-rs-sys dependency is configured to use the rust system allocator
71+
#[cfg(all(feature = "any_zlib", feature = "libz-rs-sys"))]
72+
zalloc: None,
73+
#[cfg(all(feature = "any_zlib", feature = "libz-rs-sys"))]
74+
zfree: None,
6375
})),
6476
}
6577
}
@@ -75,54 +87,63 @@ impl Drop for StreamWrapper {
7587
}
7688
}
7789

78-
const ALIGN: usize = std::mem::align_of::<usize>();
90+
#[cfg(all(feature = "any_zlib", not(feature = "libz-rs-sys")))]
91+
mod allocator {
92+
use super::*;
7993

80-
fn align_up(size: usize, align: usize) -> usize {
81-
(size + align - 1) & !(align - 1)
82-
}
94+
use std::alloc::{self, Layout};
95+
use std::convert::TryFrom;
96+
use std::os::raw::c_void;
97+
98+
const ALIGN: usize = std::mem::align_of::<usize>();
99+
100+
fn align_up(size: usize, align: usize) -> usize {
101+
(size + align - 1) & !(align - 1)
102+
}
103+
104+
pub extern "C" fn zalloc(_ptr: *mut c_void, items: uInt, item_size: uInt) -> *mut c_void {
105+
// We need to multiply `items` and `item_size` to get the actual desired
106+
// allocation size. Since `zfree` doesn't receive a size argument we
107+
// also need to allocate space for a `usize` as a header so we can store
108+
// how large the allocation is to deallocate later.
109+
let size = match items
110+
.checked_mul(item_size)
111+
.and_then(|i| usize::try_from(i).ok())
112+
.map(|size| align_up(size, ALIGN))
113+
.and_then(|i| i.checked_add(std::mem::size_of::<usize>()))
114+
{
115+
Some(i) => i,
116+
None => return ptr::null_mut(),
117+
};
118+
119+
// Make sure the `size` isn't too big to fail `Layout`'s restrictions
120+
let layout = match Layout::from_size_align(size, ALIGN) {
121+
Ok(layout) => layout,
122+
Err(_) => return ptr::null_mut(),
123+
};
83124

84-
extern "C" fn zalloc(_ptr: *mut c_void, items: AllocSize, item_size: AllocSize) -> *mut c_void {
85-
// We need to multiply `items` and `item_size` to get the actual desired
86-
// allocation size. Since `zfree` doesn't receive a size argument we
87-
// also need to allocate space for a `usize` as a header so we can store
88-
// how large the allocation is to deallocate later.
89-
let size = match items
90-
.checked_mul(item_size)
91-
.and_then(|i| usize::try_from(i).ok())
92-
.map(|size| align_up(size, ALIGN))
93-
.and_then(|i| i.checked_add(std::mem::size_of::<usize>()))
94-
{
95-
Some(i) => i,
96-
None => return ptr::null_mut(),
97-
};
98-
99-
// Make sure the `size` isn't too big to fail `Layout`'s restrictions
100-
let layout = match Layout::from_size_align(size, ALIGN) {
101-
Ok(layout) => layout,
102-
Err(_) => return ptr::null_mut(),
103-
};
104-
105-
unsafe {
106-
// Allocate the data, and if successful store the size we allocated
107-
// at the beginning and then return an offset pointer.
108-
let ptr = alloc::alloc(layout) as *mut usize;
109-
if ptr.is_null() {
110-
return ptr as *mut c_void;
125+
unsafe {
126+
// Allocate the data, and if successful store the size we allocated
127+
// at the beginning and then return an offset pointer.
128+
let ptr = alloc::alloc(layout) as *mut usize;
129+
if ptr.is_null() {
130+
return ptr as *mut c_void;
131+
}
132+
*ptr = size;
133+
ptr.add(1) as *mut c_void
111134
}
112-
*ptr = size;
113-
ptr.add(1) as *mut c_void
114135
}
115-
}
116136

117-
extern "C" fn zfree(_ptr: *mut c_void, address: *mut c_void) {
118-
unsafe {
119-
// Move our address being freed back one pointer, read the size we
120-
// stored in `zalloc`, and then free it using the standard Rust
121-
// allocator.
122-
let ptr = (address as *mut usize).offset(-1);
123-
let size = *ptr;
124-
let layout = Layout::from_size_align_unchecked(size, ALIGN);
125-
alloc::dealloc(ptr as *mut u8, layout)
137+
pub extern "C" fn zfree(_ptr: *mut c_void, address: *mut c_void) {
138+
unsafe {
139+
// Move our address being freed back one pointer, read the size we
140+
// stored in `zalloc`, and then free it using the standard Rust
141+
// allocator.
142+
let ptr = (address as *mut usize).offset(-1);
143+
let size = *ptr;
144+
let layout = Layout::from_size_align_unchecked(size, ALIGN);
145+
alloc::dealloc(ptr as *mut u8, layout)
146+
}
126147
}
127148
}
128149

@@ -382,10 +403,17 @@ mod c_backend {
382403
#[cfg(feature = "zlib-ng")]
383404
use libz_ng_sys as libz;
384405

406+
#[cfg(feature = "zlib-rs")]
407+
use libz_rs_sys as libz;
408+
385409
#[cfg(all(not(feature = "zlib-ng"), feature = "cloudflare_zlib"))]
386410
use cloudflare_zlib_sys as libz;
387411

388-
#[cfg(all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng")))]
412+
#[cfg(all(
413+
not(feature = "cloudflare_zlib"),
414+
not(feature = "zlib-ng"),
415+
not(feature = "zlib-rs")
416+
))]
389417
use libz_sys as libz;
390418

391419
pub use libz::deflate as mz_deflate;
@@ -410,13 +438,14 @@ mod c_backend {
410438
pub use libz::Z_STREAM_END as MZ_STREAM_END;
411439
pub use libz::Z_STREAM_ERROR as MZ_STREAM_ERROR;
412440
pub use libz::Z_SYNC_FLUSH as MZ_SYNC_FLUSH;
413-
pub type AllocSize = libz::uInt;
414441

415442
pub const MZ_DEFAULT_WINDOW_BITS: c_int = 15;
416443

417444
#[cfg(feature = "zlib-ng")]
418445
const ZLIB_VERSION: &'static str = "2.1.0.devel\0";
419-
#[cfg(not(feature = "zlib-ng"))]
446+
#[cfg(feature = "zlib-rs")]
447+
const ZLIB_VERSION: &'static str = "0.1.0\0";
448+
#[cfg(not(any(feature = "zlib-ng", feature = "zlib-rs")))]
420449
const ZLIB_VERSION: &'static str = "1.2.8\0";
421450

422451
pub unsafe extern "C" fn mz_deflateInit2(

0 commit comments

Comments
 (0)