flate2/ffi/
mod.rs

1//! This module contains backend-specific code.
2
3use crate::mem::{CompressError, DecompressError, FlushCompress, FlushDecompress, Status};
4use crate::Compression;
5use std::mem::MaybeUninit;
6
7fn initialize_buffer(output: &mut [MaybeUninit<u8>]) -> &mut [u8] {
8    // SAFETY: Here we zero-initialize the output and cast it to [u8]
9    unsafe {
10        output.as_mut_ptr().write_bytes(0, output.len());
11        &mut *(output as *mut [MaybeUninit<u8>] as *mut [u8])
12    }
13}
14
15/// Traits specifying the interface of the backends.
16///
17/// Sync + Send are added as a condition to ensure they are available
18/// for the frontend.
19pub trait Backend: Sync + Send {
20    fn total_in(&self) -> u64;
21    fn total_out(&self) -> u64;
22}
23
24pub trait InflateBackend: Backend {
25    fn make(zlib_header: bool, window_bits: u8) -> Self;
26    fn decompress(
27        &mut self,
28        input: &[u8],
29        output: &mut [u8],
30        flush: FlushDecompress,
31    ) -> Result<Status, DecompressError>;
32    fn decompress_uninit(
33        &mut self,
34        input: &[u8],
35        output: &mut [MaybeUninit<u8>],
36        flush: FlushDecompress,
37    ) -> Result<Status, DecompressError> {
38        self.decompress(input, initialize_buffer(output), flush)
39    }
40    fn reset(&mut self, zlib_header: bool);
41}
42
43pub trait DeflateBackend: Backend {
44    fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self;
45    fn compress(
46        &mut self,
47        input: &[u8],
48        output: &mut [u8],
49        flush: FlushCompress,
50    ) -> Result<Status, CompressError>;
51    fn compress_uninit(
52        &mut self,
53        input: &[u8],
54        output: &mut [MaybeUninit<u8>],
55        flush: FlushCompress,
56    ) -> Result<Status, CompressError> {
57        self.compress(input, initialize_buffer(output), flush)
58    }
59    fn reset(&mut self);
60}
61
62// Default to Rust implementation unless explicitly opted in to a different backend.
63#[cfg(feature = "any_c_zlib")]
64mod c;
65#[cfg(feature = "any_c_zlib")]
66pub use self::c::*;
67
68// Only bring in `zlib-rs` if there is no C-based backend.
69#[cfg(all(not(feature = "any_c_zlib"), feature = "zlib-rs"))]
70mod zlib_rs;
71#[cfg(all(not(feature = "any_c_zlib"), feature = "zlib-rs"))]
72pub use self::zlib_rs::*;
73
74// Use miniz_oxide when no fully compliant zlib is selected.
75#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))]
76mod miniz_oxide;
77#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))]
78pub use self::miniz_oxide::*;
79
80// If no backend is enabled, fail fast with a clear error message.
81#[cfg(not(feature = "any_impl"))]
82compile_error!("No compression backend selected; enable one of `zlib`, `zlib-ng`, `zlib-rs`, or the default `rust_backend` feature.");
83
84impl std::fmt::Debug for ErrorMessage {
85    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
86        self.get().fmt(f)
87    }
88}