Skip to main content

compression_codecs/
lib.rs

1//! Adaptors for various compression algorithms.
2
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5use std::io::Result;
6
7pub use compression_core as core;
8
9#[cfg(feature = "brotli")]
10pub mod brotli;
11#[cfg(feature = "bzip2")]
12pub mod bzip2;
13#[cfg(feature = "deflate")]
14pub mod deflate;
15#[cfg(feature = "deflate64")]
16pub mod deflate64;
17#[cfg(feature = "flate2")]
18pub mod flate;
19#[cfg(feature = "gzip")]
20pub mod gzip;
21#[cfg(feature = "lz4")]
22pub mod lz4;
23#[cfg(feature = "lzma")]
24pub mod lzma;
25#[cfg(all(feature = "brotli-mbrotli", async_compression_unstable))]
26pub mod mbrotli;
27#[cfg(all(feature = "zstd-mzstd", async_compression_unstable))]
28pub mod mzstd;
29#[cfg(feature = "xz")]
30pub mod xz;
31#[cfg(feature = "lzma")]
32pub mod xz2;
33#[cfg(feature = "zlib")]
34pub mod zlib;
35#[cfg(feature = "zstd")]
36pub mod zstd;
37
38use compression_core::util::{PartialBuffer, WriteBuffer};
39
40#[cfg(feature = "brotli")]
41pub use self::brotli::{BrotliDecoder, BrotliEncoder};
42#[cfg(feature = "bzip2")]
43pub use self::bzip2::{BzDecoder, BzEncoder};
44#[cfg(feature = "deflate")]
45pub use self::deflate::{DeflateDecoder, DeflateEncoder};
46#[cfg(feature = "deflate64")]
47pub use self::deflate64::Deflate64Decoder;
48#[cfg(feature = "flate2")]
49pub use self::flate::{FlateDecoder, FlateEncoder};
50#[cfg(feature = "gzip")]
51pub use self::gzip::{GzipDecoder, GzipEncoder};
52#[cfg(feature = "lz4")]
53pub use self::lz4::{Lz4Decoder, Lz4Encoder};
54#[cfg(feature = "lzma")]
55pub use self::lzma::{LzmaDecoder, LzmaEncoder};
56#[cfg(all(feature = "brotli-mbrotli", async_compression_unstable))]
57pub use self::mbrotli::{MbrotliDecoder, MbrotliEncoder};
58#[cfg(all(feature = "zstd-mzstd", async_compression_unstable))]
59pub use self::mzstd::{MzstdDecoder, MzstdEncoder};
60#[cfg(feature = "xz")]
61pub use self::xz::{XzDecoder, XzEncoder};
62#[cfg(feature = "lzma")]
63pub use self::xz2::{Xz2Decoder, Xz2Encoder, Xz2FileFormat};
64#[cfg(feature = "zlib")]
65pub use self::zlib::{ZlibDecoder, ZlibEncoder};
66#[cfg(feature = "zstd")]
67pub use self::zstd::{ZstdDecoder, ZstdEncoder};
68
69fn forward_output<R>(
70    output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
71    f: impl FnOnce(&mut WriteBuffer<'_>) -> R,
72) -> R {
73    let written_len = output.written_len();
74
75    let output_buffer = output.get_mut();
76    let mut write_buffer = WriteBuffer::new_initialized(output_buffer.as_mut());
77    write_buffer.advance(written_len);
78
79    let result = f(&mut write_buffer);
80    let new_written_len = write_buffer.written_len();
81    output.advance(new_written_len - written_len);
82    result
83}
84
85fn forward_input_output<R>(
86    input: &mut PartialBuffer<impl AsRef<[u8]>>,
87    output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
88    f: impl FnOnce(&mut PartialBuffer<&[u8]>, &mut WriteBuffer<'_>) -> R,
89) -> R {
90    let written_len = input.written_len();
91
92    let input_buffer = input.get_mut();
93    let mut partial_buffer = PartialBuffer::new(input_buffer.as_ref());
94    partial_buffer.advance(written_len);
95
96    let result = forward_output(output, |output| f(&mut partial_buffer, output));
97    let new_written_len = partial_buffer.written_len();
98    input.advance(new_written_len - written_len);
99    result
100}
101
102pub trait Encode {
103    fn encode(
104        &mut self,
105        input: &mut PartialBuffer<impl AsRef<[u8]>>,
106        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
107    ) -> Result<()>;
108
109    /// Returns whether the internal buffers are flushed
110    fn flush(&mut self, output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>)
111        -> Result<bool>;
112
113    /// Returns whether the internal buffers are flushed and the end of the stream is written
114    fn finish(
115        &mut self,
116        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
117    ) -> Result<bool>;
118}
119impl<T: EncodeV2 + ?Sized> Encode for T {
120    fn encode(
121        &mut self,
122        input: &mut PartialBuffer<impl AsRef<[u8]>>,
123        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
124    ) -> Result<()> {
125        forward_input_output(input, output, |input, output| {
126            EncodeV2::encode(self, input, output)
127        })
128    }
129
130    fn flush(
131        &mut self,
132        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
133    ) -> Result<bool> {
134        forward_output(output, |output| EncodeV2::flush(self, output))
135    }
136
137    fn finish(
138        &mut self,
139        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
140    ) -> Result<bool> {
141        forward_output(output, |output| EncodeV2::finish(self, output))
142    }
143}
144
145/// version 2 of [`Encode`] that is trait object safe.
146///
147/// The different from [`Encode`] is that:
148///  - It doesn't have any generic in it, so it is trait object safe
149///  - It uses [`WriteBuffer`] for output, which will support uninitialized buffer.
150pub trait EncodeV2 {
151    fn encode(
152        &mut self,
153        input: &mut PartialBuffer<&[u8]>,
154        output: &mut WriteBuffer<'_>,
155    ) -> Result<()>;
156
157    /// Returns whether the internal buffers are flushed
158    fn flush(&mut self, output: &mut WriteBuffer<'_>) -> Result<bool>;
159
160    /// Returns whether the internal buffers are flushed and the end of the stream is written
161    fn finish(&mut self, output: &mut WriteBuffer<'_>) -> Result<bool>;
162}
163
164pub trait Decode {
165    /// Reinitializes this decoder ready to decode a new member/frame of data.
166    fn reinit(&mut self) -> Result<()>;
167
168    /// Returns whether the end of the stream has been read
169    fn decode(
170        &mut self,
171        input: &mut PartialBuffer<impl AsRef<[u8]>>,
172        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
173    ) -> Result<bool>;
174
175    /// Returns whether the internal buffers are flushed
176    fn flush(&mut self, output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>)
177        -> Result<bool>;
178
179    /// Returns whether the internal buffers are flushed
180    fn finish(
181        &mut self,
182        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
183    ) -> Result<bool>;
184}
185
186impl<T: DecodeV2 + ?Sized> Decode for T {
187    fn reinit(&mut self) -> Result<()> {
188        DecodeV2::reinit(self)
189    }
190
191    fn decode(
192        &mut self,
193        input: &mut PartialBuffer<impl AsRef<[u8]>>,
194        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
195    ) -> Result<bool> {
196        forward_input_output(input, output, |input, output| {
197            DecodeV2::decode(self, input, output)
198        })
199    }
200
201    fn flush(
202        &mut self,
203        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
204    ) -> Result<bool> {
205        forward_output(output, |output| DecodeV2::flush(self, output))
206    }
207
208    fn finish(
209        &mut self,
210        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
211    ) -> Result<bool> {
212        forward_output(output, |output| DecodeV2::finish(self, output))
213    }
214}
215
216/// version 2 [`Decode`] that is trait object safe.
217///
218/// The different from [`Decode`] is that:
219///  - It doesn't have any generic in it, so it is trait object safe
220///  - It uses [`WriteBuffer`] for output, which will support uninitialized buffer.
221pub trait DecodeV2 {
222    /// Reinitializes this decoder ready to decode a new member/frame of data.
223    fn reinit(&mut self) -> Result<()>;
224
225    /// Returns whether the end of the stream has been read
226    fn decode(
227        &mut self,
228        input: &mut PartialBuffer<&[u8]>,
229        output: &mut WriteBuffer<'_>,
230    ) -> Result<bool>;
231
232    /// Returns whether the internal buffers are flushed
233    fn flush(&mut self, output: &mut WriteBuffer<'_>) -> Result<bool>;
234
235    /// Returns whether the internal buffers are flushed
236    fn finish(&mut self, output: &mut WriteBuffer<'_>) -> Result<bool>;
237}
238
239pub trait DecodedSize {
240    /// Returns the size of the input when uncompressed.
241    fn decoded_size(input: &[u8]) -> Result<u64>;
242}