1 | use crate::tags::CompressionMethod; |
2 | use std::io::{self, Write}; |
3 | |
4 | mod deflate; |
5 | mod lzw; |
6 | mod packbits; |
7 | mod uncompressed; |
8 | |
9 | pub use self::deflate::{Deflate, DeflateLevel}; |
10 | pub use self::lzw::Lzw; |
11 | pub use self::packbits::Packbits; |
12 | pub use self::uncompressed::Uncompressed; |
13 | |
14 | /// An algorithm used for compression |
15 | pub trait CompressionAlgorithm { |
16 | /// The algorithm writes data directly into the writer. |
17 | /// It returns the total number of bytes written. |
18 | fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error>; |
19 | } |
20 | |
21 | /// An algorithm used for compression with associated enums and optional configurations. |
22 | pub trait Compression: CompressionAlgorithm { |
23 | /// The corresponding tag to the algorithm. |
24 | const COMPRESSION_METHOD: CompressionMethod; |
25 | |
26 | /// Method to optain a type that can store each variant of comression algorithm. |
27 | fn get_algorithm(&self) -> Compressor; |
28 | } |
29 | |
30 | /// An enum to store each compression algorithm. |
31 | pub enum Compressor { |
32 | Uncompressed(Uncompressed), |
33 | Lzw(Lzw), |
34 | Deflate(Deflate), |
35 | Packbits(Packbits), |
36 | } |
37 | |
38 | impl Default for Compressor { |
39 | /// The default compression strategy does not apply any compression. |
40 | fn default() -> Self { |
41 | Compressor::Uncompressed(Uncompressed) |
42 | } |
43 | } |
44 | |
45 | impl CompressionAlgorithm for Compressor { |
46 | fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error> { |
47 | match self { |
48 | Compressor::Uncompressed(algorithm: &mut Uncompressed) => algorithm.write_to(writer, bytes), |
49 | Compressor::Lzw(algorithm: &mut Lzw) => algorithm.write_to(writer, bytes), |
50 | Compressor::Deflate(algorithm: &mut Deflate) => algorithm.write_to(writer, bytes), |
51 | Compressor::Packbits(algorithm: &mut Packbits) => algorithm.write_to(writer, bytes), |
52 | } |
53 | } |
54 | } |
55 | |
56 | #[cfg (test)] |
57 | mod tests { |
58 | pub const TEST_DATA: &[u8] = b"This is a string for checking various compression algorithms." ; |
59 | } |
60 | |