pubstruct StreamWrapper { // SAFETY: The field `inner` must always be accessed as a raw pointer, // since it points to a cyclic structure, and it must never be copied // by Rust. pub inner: *mut mz_stream,
}
impl Default for StreamWrapper { fn default() -> StreamWrapper { // SAFETY: The field `state` will be initialized across the FFI to // point to the opaque type `mz_internal_state`, which will contain a copy // of `inner`. This cyclic structure breaks the uniqueness invariant of // &mut mz_stream, so we must use a raw pointer instead of Box<mz_stream>.
StreamWrapper {
inner: Box::into_raw(Box::new(mz_stream {
next_in: ptr::null_mut(),
avail_in: 0,
total_in: 0,
next_out: ptr::null_mut(),
avail_out: 0,
total_out: 0,
msg: ptr::null_mut(),
adler: 0,
data_type: 0,
reserved: 0,
opaque: ptr::null_mut(),
state: ptr::null_mut(), #[cfg(all(
feature = "any_zlib",
not(any(feature = "cloudflare-zlib-sys", feature = "libz-rs-sys"))
))]
zalloc: allocator::zalloc, #[cfg(all(
feature = "any_zlib",
not(any(feature = "cloudflare-zlib-sys", feature = "libz-rs-sys"))
))]
zfree: allocator::zfree,
// for zlib-rs, it is most efficient to have it provide the allocator. // The libz-rs-sys dependency is configured to use the rust system allocator #[cfg(all(feature = "any_zlib", feature = "libz-rs-sys"))]
zalloc: None, #[cfg(all(feature = "any_zlib", feature = "libz-rs-sys"))]
zfree: None,
})),
}
}
}
impl Drop for StreamWrapper { fn drop(&mutself) { // SAFETY: At this point, every other allocation for struct has been freed by // `inflateEnd` or `deflateEnd`, and no copies of `inner` are retained by `C`, // so it is safe to drop the struct as long as the user respects the invariant that // `inner` must never be copied by Rust.
drop(unsafe { Box::from_raw(self.inner) });
}
}
#[cfg(all(feature = "any_zlib", not(feature = "libz-rs-sys")))] mod allocator { usesuper::*;
use std::alloc::{self, Layout}; use std::convert::TryFrom; use std::os::raw::c_void;
pubextern"C"fn zalloc(_ptr: *mut c_void, items: uInt, item_size: uInt) -> *mut c_void { // We need to multiply `items` and `item_size` to get the actual desired // allocation size. Since `zfree` doesn't receive a size argument we // also need to allocate space for a `usize` as a header so we can store // how large the allocation is to deallocate later. let size = match items
.checked_mul(item_size)
.and_then(|i| usize::try_from(i).ok())
.map(|size| align_up(size, ALIGN))
.and_then(|i| i.checked_add(std::mem::size_of::<usize>()))
{
Some(i) => i,
None => return ptr::null_mut(),
};
// Make sure the `size` isn't too big to fail `Layout`'s restrictions let layout = match Layout::from_size_align(size, ALIGN) {
Ok(layout) => layout,
Err(_) => return ptr::null_mut(),
};
unsafe { // Allocate the data, and if successful store the size we allocated // at the beginning and then return an offset pointer. let ptr = alloc::alloc(layout) as *mut usize; if ptr.is_null() { return ptr as *mut c_void;
}
*ptr = size;
ptr.add(1) as *mut c_void
}
}
pubextern"C"fn zfree(_ptr: *mut c_void, address: *mut c_void) { unsafe { // Move our address being freed back one pointer, read the size we // stored in `zalloc`, and then free it using the standard Rust // allocator. let ptr = (address as *mut usize).offset(-1); let size = *ptr; let layout = Layout::from_size_align_unchecked(size, ALIGN);
alloc::dealloc(ptr as *mut u8, layout)
}
}
}
unsafeimpl<D: Direction> Send for Stream<D> {} unsafeimpl<D: Direction> Sync for Stream<D> {}
/// Trait used to call the right destroy/end function on the inner /// stream object on drop. pubtrait Direction { unsafefn destroy(stream: *mut mz_stream) -> c_int;
}
impl<D: Direction> Stream<D> { pubfn msg(&self) -> ErrorMessage { // SAFETY: The field `inner` must always be accessed as a raw pointer, // since it points to a cyclic structure. No copies of `inner` can be // retained for longer than the lifetime of `self`. let msg = unsafe { (*self.stream_wrapper.inner).msg };
ErrorMessage(if msg.is_null() {
None
} else { let s = unsafe { std::ffi::CStr::from_ptr(msg) };
std::str::from_utf8(s.to_bytes()).ok()
})
}
}
impl<D: Direction> Drop for Stream<D> { fn drop(&mutself) { unsafe { let _ = D::destroy(self.stream_wrapper.inner);
}
}
}
impl Direction for DirCompress { unsafefn destroy(stream: *mut mz_stream) -> c_int {
mz_deflateEnd(stream)
}
} impl Direction for DirDecompress { unsafefn destroy(stream: *mut mz_stream) -> c_int {
mz_inflateEnd(stream)
}
}
impl InflateBackend for Inflate { fn make(zlib_header: bool, window_bits: u8) -> Self { unsafe { let state = StreamWrapper::default(); let ret = mz_inflateInit2(
state.inner, if zlib_header {
window_bits as c_int
} else {
-(window_bits as c_int)
},
);
assert_eq!(ret, 0);
Inflate {
inner: Stream {
stream_wrapper: state,
total_in: 0,
total_out: 0,
_marker: marker::PhantomData,
},
}
}
}
fn decompress(
&mutself,
input: &[u8],
output: &mut [u8],
flush: FlushDecompress,
) -> Result<Status, DecompressError> { let raw = self.inner.stream_wrapper.inner; // SAFETY: The field `inner` must always be accessed as a raw pointer, // since it points to a cyclic structure. No copies of `inner` can be // retained for longer than the lifetime of `self`. unsafe {
(*raw).msg = ptr::null_mut();
(*raw).next_in = input.as_ptr() as *mut u8;
(*raw).avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint;
(*raw).next_out = output.as_mut_ptr();
(*raw).avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint;
let rc = mz_inflate(raw, flush as c_int);
// Unfortunately the total counters provided by zlib might be only // 32 bits wide and overflow while processing large amounts of data. self.inner.total_in += ((*raw).next_in as usize - input.as_ptr() as usize) as u64; self.inner.total_out += ((*raw).next_out as usize - output.as_ptr() as usize) as u64;
// reset these pointers so we don't accidentally read them later
(*raw).next_in = ptr::null_mut();
(*raw).avail_in = 0;
(*raw).next_out = ptr::null_mut();
(*raw).avail_out = 0;
impl DeflateBackend for Deflate { fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self { unsafe { let state = StreamWrapper::default(); let ret = mz_deflateInit2(
state.inner,
level.0as c_int,
MZ_DEFLATED, if zlib_header {
window_bits as c_int
} else {
-(window_bits as c_int)
}, 8,
MZ_DEFAULT_STRATEGY,
);
assert_eq!(ret, 0);
Deflate {
inner: Stream {
stream_wrapper: state,
total_in: 0,
total_out: 0,
_marker: marker::PhantomData,
},
}
}
} fn compress(
&mutself,
input: &[u8],
output: &mut [u8],
flush: FlushCompress,
) -> Result<Status, CompressError> { let raw = self.inner.stream_wrapper.inner; // SAFETY: The field `inner` must always be accessed as a raw pointer, // since it points to a cyclic structure. No copies of `inner` can be // retained for longer than the lifetime of `self`. unsafe {
(*raw).msg = ptr::null_mut();
(*raw).next_in = input.as_ptr() as *mut _;
(*raw).avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint;
(*raw).next_out = output.as_mut_ptr();
(*raw).avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint;
let rc = mz_deflate(raw, flush as c_int);
// Unfortunately the total counters provided by zlib might be only // 32 bits wide and overflow while processing large amounts of data.
self.inner.total_in += ((*raw).next_in as usize - input.as_ptr() as usize) as u64; self.inner.total_out += ((*raw).next_out as usize - output.as_ptr() as usize) as u64; // reset these pointers so we don't accidentally read them later
(*raw).next_in = ptr::null_mut();
(*raw).avail_in = 0;
(*raw).next_out = ptr::null_mut();
(*raw).avail_out = 0;
/// For backwards compatibility, we provide symbols as `mz_` to mimic the miniz API #[allow(bad_style)] #[allow(unused_imports)] mod c_backend { use std::mem; use std::os::raw::{c_char, c_int};
#[cfg(feature = "zlib-ng")] use libz_ng_sys as libz;
#[cfg(all(not(feature = "zlib-ng"), feature = "zlib-rs"))] use libz_rs_sys as libz;
#[cfg(all(not(feature = "zlib-ng"), feature = "cloudflare_zlib"))] use cloudflare_zlib_sys as libz;
#[cfg(all(
not(feature = "cloudflare_zlib"),
not(feature = "zlib-ng"),
not(feature = "zlib-rs")
))] use libz_sys as libz;
pubuse libz::deflate as mz_deflate; pubuse libz::deflateEnd as mz_deflateEnd; pubuse libz::deflateReset as mz_deflateReset; pubuse libz::inflate as mz_inflate; pubuse libz::inflateEnd as mz_inflateEnd; pubuse libz::z_stream as mz_stream; pubuse libz::*;
pubuse libz::Z_BLOCK as MZ_BLOCK; pubuse libz::Z_BUF_ERROR as MZ_BUF_ERROR; pubuse libz::Z_DATA_ERROR as MZ_DATA_ERROR; pubuse libz::Z_DEFAULT_STRATEGY as MZ_DEFAULT_STRATEGY; pubuse libz::Z_DEFLATED as MZ_DEFLATED; pubuse libz::Z_FINISH as MZ_FINISH; pubuse libz::Z_FULL_FLUSH as MZ_FULL_FLUSH; pubuse libz::Z_NEED_DICT as MZ_NEED_DICT; pubuse libz::Z_NO_FLUSH as MZ_NO_FLUSH; pubuse libz::Z_OK as MZ_OK; pubuse libz::Z_PARTIAL_FLUSH as MZ_PARTIAL_FLUSH; pubuse libz::Z_STREAM_END as MZ_STREAM_END; pubuse libz::Z_STREAM_ERROR as MZ_STREAM_ERROR; pubuse libz::Z_SYNC_FLUSH as MZ_SYNC_FLUSH;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.