Skip to content

Commit 50f9913

Browse files
committed
Skip libz-rs-sys when using the zlib-rs backend
1 parent 8ad8fd7 commit 50f9913

File tree

6 files changed

+205
-29
lines changed

6 files changed

+205
-29
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ libz-sys = { version = "1.1.20", optional = true, default-features = false }
2323
libz-ng-sys = { version = "1.1.16", optional = true }
2424
# this matches the default features, but we don't want to depend on the default features staying the same
2525
libz-rs-sys = { version = "0.5.1", optional = true, default-features = false, features = ["std", "rust-allocator"] }
26+
zlib-rs = { git = "https://github.com/trifectatechfoundation/zlib-rs.git", rev = "bc0c9fd8b29a5ba64869717f47cb241008621f30", optional = true, default-features = false, features = ["std", "rust-allocator"] }
2627
cloudflare-zlib-sys = { version = "0.3.6", optional = true }
2728
miniz_oxide = { version = "0.8.5", optional = true, default-features = false, features = ["with-alloc", "simd"] }
2829
crc32fast = "1.2.0"
@@ -43,7 +44,7 @@ zlib = ["any_zlib", "libz-sys"]
4344
zlib-default = ["any_zlib", "libz-sys/default"]
4445
zlib-ng-compat = ["zlib", "libz-sys/zlib-ng"]
4546
zlib-ng = ["any_zlib", "libz-ng-sys"]
46-
zlib-rs = ["any_zlib", "libz-rs-sys"]
47+
zlib-rs = ["any_impl", "dep:zlib-rs", "dep:libz-rs-sys"]
4748
cloudflare_zlib = ["any_zlib", "cloudflare-zlib-sys"]
4849
rust_backend = ["miniz_oxide", "any_impl"]
4950
miniz-sys = ["rust_backend"] # For backwards compatibility

src/ffi/c.rs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::*;
99
use crate::mem;
1010

1111
#[derive(Clone, Default)]
12-
pub struct ErrorMessage(Option<&'static str>);
12+
pub struct ErrorMessage(pub(crate) Option<&'static str>);
1313

1414
impl ErrorMessage {
1515
pub fn get(&self) -> Option<&str> {
@@ -55,34 +55,27 @@ impl Default for StreamWrapper {
5555
// zlib-ng
5656
feature = "zlib-ng",
5757
// libz-sys
58-
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs"))
58+
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"))
5959
))]
6060
zalloc: allocator::zalloc,
6161
#[cfg(any(
6262
// zlib-ng
6363
feature = "zlib-ng",
6464
// libz-sys
65-
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs"))
65+
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"))
6666
))]
6767
zfree: allocator::zfree,
6868

6969
#[cfg(
7070
// cloudflare-zlib
71-
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
71+
all(feature = "cloudflare_zlib", not(feature = "zlib-ng")),
7272
)]
7373
zalloc: Some(allocator::zalloc),
7474
#[cfg(
7575
// cloudflare-zlib
76-
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
76+
all(feature = "cloudflare_zlib", not(feature = "zlib-ng")),
7777
)]
7878
zfree: Some(allocator::zfree),
79-
80-
// for zlib-rs, it is most efficient to have it provide the allocator.
81-
// The libz-rs-sys dependency is configured to use the rust system allocator
82-
#[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))]
83-
zalloc: None,
84-
#[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))]
85-
zfree: None,
8679
})),
8780
}
8881
}
@@ -102,9 +95,9 @@ impl Drop for StreamWrapper {
10295
// zlib-ng
10396
feature = "zlib-ng",
10497
// cloudflare-zlib
105-
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
98+
all(feature = "cloudflare_zlib", not(feature = "zlib-ng")),
10699
// libz-sys
107-
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")),
100+
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng")),
108101
))]
109102
mod allocator {
110103
use super::*;
@@ -462,18 +455,15 @@ mod c_backend {
462455
#[cfg(feature = "zlib-ng")]
463456
use libz_ng_sys as libz;
464457

465-
#[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))]
466-
use libz_rs_sys as libz;
467-
468458
#[cfg(
469459
// cloudflare-zlib
470-
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
460+
all(feature = "cloudflare_zlib", not(feature = "zlib-ng")),
471461
)]
472462
use cloudflare_zlib_sys as libz;
473463

474464
#[cfg(
475465
// libz-sys
476-
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")),
466+
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng")),
477467
)]
478468
use libz_sys as libz;
479469

src/ffi/rust.rs renamed to src/ffi/miniz_oxide.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
use std::convert::TryInto;
44
use std::fmt;
55

6-
use miniz_oxide::deflate::core::CompressorOxide;
7-
use miniz_oxide::inflate::stream::InflateState;
8-
pub use miniz_oxide::*;
6+
use ::miniz_oxide::deflate::core::CompressorOxide;
7+
use ::miniz_oxide::inflate::stream::InflateState;
8+
pub use ::miniz_oxide::*;
99

1010
pub const MZ_NO_FLUSH: isize = MZFlush::None as isize;
1111
pub const MZ_PARTIAL_FLUSH: isize = MZFlush::Partial as isize;
@@ -146,7 +146,7 @@ impl From<FlushCompress> for MZFlush {
146146
impl DeflateBackend for Deflate {
147147
fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self {
148148
// Check in case the integer value changes at some point.
149-
debug_assert!(level.level() <= 10);
149+
debug_assert!(level.level() <= 9);
150150

151151
let mut inner: Box<CompressorOxide> = Box::default();
152152
let format = format_from_bool(zlib_header);

src/ffi/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,15 @@ mod c;
6565
#[cfg(feature = "any_zlib")]
6666
pub use self::c::*;
6767

68+
#[cfg(all(not(feature = "any_zlib"), feature = "zlib-rs"))]
69+
mod zlib_rs;
70+
#[cfg(all(not(feature = "any_zlib"), feature = "zlib-rs"))]
71+
pub use self::zlib_rs::*;
72+
6873
#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))]
69-
mod rust;
74+
mod miniz_oxide;
7075
#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))]
71-
pub use self::rust::*;
76+
pub use self::miniz_oxide::*;
7277

7378
impl std::fmt::Debug for ErrorMessage {
7479
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {

src/ffi/zlib_rs.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
//! Implementation for `zlib_rs` rust backend.
2+
//!
3+
//! Every backend must provide two types:
4+
//!
5+
//! - `Deflate` for compression, implements the `Backend` and `DeflateBackend` trait
6+
//! - `Inflate` for decompression, implements the `Backend` and `InflateBackend` trait
7+
//!
8+
//! Additionally the backend provides a number of constants, and a `ErrorMessage` type.
9+
//!
10+
//! ## Allocation
11+
//!
12+
//! The (de)compression state is not boxed. The C implementations require that the z_stream is
13+
//! pinned in memory (has a fixed address), because their z_stream is self-referential. The most
14+
//! convenient way in rust to guarantee a stable address is to `Box` the data, but it does add an
15+
//! additional allocation.
16+
//!
17+
//! With zlib_rs the state is not self-referential and hence no boxing is needed. The `new` methods
18+
//! internally do allocate space for the (de)compression state.
19+
20+
use std::fmt;
21+
22+
use ::zlib_rs::{DeflateFlush, InflateError, InflateFlush};
23+
24+
pub const MZ_NO_FLUSH: isize = DeflateFlush::NoFlush as isize;
25+
pub const MZ_PARTIAL_FLUSH: isize = DeflateFlush::PartialFlush as isize;
26+
pub const MZ_SYNC_FLUSH: isize = DeflateFlush::SyncFlush as isize;
27+
pub const MZ_FULL_FLUSH: isize = DeflateFlush::FullFlush as isize;
28+
pub const MZ_FINISH: isize = DeflateFlush::Finish as isize;
29+
30+
pub const MZ_DEFAULT_WINDOW_BITS: core::ffi::c_int = 15;
31+
32+
use super::*;
33+
34+
impl From<::zlib_rs::Status> for crate::mem::Status {
35+
fn from(value: ::zlib_rs::Status) -> Self {
36+
match value {
37+
::zlib_rs::Status::Ok => crate::mem::Status::Ok,
38+
::zlib_rs::Status::BufError => crate::mem::Status::BufError,
39+
::zlib_rs::Status::StreamEnd => crate::mem::Status::StreamEnd,
40+
}
41+
}
42+
}
43+
44+
#[derive(Clone, Default)]
45+
pub struct ErrorMessage(Option<&'static str>);
46+
47+
impl ErrorMessage {
48+
pub fn get(&self) -> Option<&str> {
49+
self.0
50+
}
51+
}
52+
53+
pub struct Inflate {
54+
pub(crate) inner: ::zlib_rs::Inflate,
55+
}
56+
57+
impl fmt::Debug for Inflate {
58+
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
59+
write!(
60+
f,
61+
"zlib_rs inflate internal state. total_in: {}, total_out: {}",
62+
self.inner.total_in(),
63+
self.inner.total_out(),
64+
)
65+
}
66+
}
67+
68+
impl From<FlushDecompress> for DeflateFlush {
69+
fn from(value: FlushDecompress) -> Self {
70+
match value {
71+
FlushDecompress::None => Self::NoFlush,
72+
FlushDecompress::Sync => Self::SyncFlush,
73+
FlushDecompress::Finish => Self::Finish,
74+
}
75+
}
76+
}
77+
78+
impl InflateBackend for Inflate {
79+
fn make(zlib_header: bool, window_bits: u8) -> Self {
80+
Inflate {
81+
inner: ::zlib_rs::Inflate::new(zlib_header, window_bits),
82+
}
83+
}
84+
85+
fn decompress(
86+
&mut self,
87+
input: &[u8],
88+
output: &mut [u8],
89+
flush: FlushDecompress,
90+
) -> Result<Status, DecompressError> {
91+
let flush = match flush {
92+
FlushDecompress::None => InflateFlush::NoFlush,
93+
FlushDecompress::Sync => InflateFlush::SyncFlush,
94+
FlushDecompress::Finish => InflateFlush::Finish,
95+
};
96+
97+
match self.inner.decompress(input, output, flush) {
98+
Ok(status) => Ok(status.into()),
99+
Err(InflateError::NeedDict { dict_id }) => crate::mem::decompress_need_dict(dict_id),
100+
Err(e) => crate::mem::decompress_failed(ErrorMessage(Some(e.as_str()))),
101+
}
102+
}
103+
104+
fn reset(&mut self, zlib_header: bool) {
105+
self.inner.reset(zlib_header);
106+
}
107+
}
108+
109+
impl Backend for Inflate {
110+
#[inline]
111+
fn total_in(&self) -> u64 {
112+
self.inner.total_in()
113+
}
114+
115+
#[inline]
116+
fn total_out(&self) -> u64 {
117+
self.inner.total_out()
118+
}
119+
}
120+
121+
pub struct Deflate {
122+
pub(crate) inner: ::zlib_rs::Deflate,
123+
}
124+
125+
impl fmt::Debug for Deflate {
126+
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
127+
write!(
128+
f,
129+
"zlib_rs deflate internal state. total_in: {}, total_out: {}",
130+
self.inner.total_in(),
131+
self.inner.total_out(),
132+
)
133+
}
134+
}
135+
136+
impl DeflateBackend for Deflate {
137+
fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self {
138+
// Check in case the integer value changes at some point.
139+
debug_assert!(level.level() <= 9);
140+
141+
Deflate {
142+
inner: ::zlib_rs::Deflate::new(level.level() as i32, zlib_header, window_bits),
143+
}
144+
}
145+
146+
fn compress(
147+
&mut self,
148+
input: &[u8],
149+
output: &mut [u8],
150+
flush: FlushCompress,
151+
) -> Result<Status, CompressError> {
152+
let flush = match flush {
153+
FlushCompress::None => DeflateFlush::NoFlush,
154+
FlushCompress::Partial => DeflateFlush::PartialFlush,
155+
FlushCompress::Sync => DeflateFlush::SyncFlush,
156+
FlushCompress::Full => DeflateFlush::FullFlush,
157+
FlushCompress::Finish => DeflateFlush::Finish,
158+
};
159+
160+
match self.inner.compress(input, output, flush) {
161+
Ok(status) => Ok(status.into()),
162+
Err(e) => crate::mem::compress_failed(ErrorMessage(Some(e.as_str()))),
163+
}
164+
}
165+
166+
fn reset(&mut self) {
167+
self.inner.reset();
168+
}
169+
}
170+
171+
impl Backend for Deflate {
172+
#[inline]
173+
fn total_in(&self) -> u64 {
174+
self.inner.total_in()
175+
}
176+
177+
#[inline]
178+
fn total_out(&self) -> u64 {
179+
self.inner.total_out()
180+
}
181+
}

src/mem.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -662,9 +662,8 @@ mod tests {
662662

663663
let mut d = Decompress::new(false);
664664
// decompressed whole deflate stream
665-
assert!(d
666-
.decompress_vec(&data[10..], &mut decoded, FlushDecompress::Finish)
667-
.is_ok());
665+
d.decompress_vec(&data[10..], &mut decoded, FlushDecompress::Finish)
666+
.unwrap();
668667

669668
// decompress data that has nothing to do with the deflate stream (this
670669
// used to panic)

0 commit comments

Comments
 (0)