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