1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use crate::tags::CompressionMethod;
use std::io::{self, Write};

mod deflate;
mod lzw;
mod packbits;
mod uncompressed;

pub use self::deflate::{Deflate, DeflateLevel};
pub use self::lzw::Lzw;
pub use self::packbits::Packbits;
pub use self::uncompressed::Uncompressed;

/// An algorithm used for compression
pub trait CompressionAlgorithm {
    /// The algorithm writes data directly into the writer.
    /// It returns the total number of bytes written.
    fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error>;
}

/// An algorithm used for compression with associated enums and optional configurations.
pub trait Compression: CompressionAlgorithm {
    /// The corresponding tag to the algorithm.
    const COMPRESSION_METHOD: CompressionMethod;

    /// Method to optain a type that can store each variant of comression algorithm.
    fn get_algorithm(&self) -> Compressor;
}

/// An enum to store each compression algorithm.
pub enum Compressor {
    Uncompressed(Uncompressed),
    Lzw(Lzw),
    Deflate(Deflate),
    Packbits(Packbits),
}

impl Default for Compressor {
    /// The default compression strategy does not apply any compression.
    fn default() -> Self {
        Compressor::Uncompressed(Uncompressed)
    }
}

impl CompressionAlgorithm for Compressor {
    fn write_to<W: Write>(&mut self, writer: &mut W, bytes: &[u8]) -> Result<u64, io::Error> {
        match self {
            Compressor::Uncompressed(algorithm) => algorithm.write_to(writer, bytes),
            Compressor::Lzw(algorithm) => algorithm.write_to(writer, bytes),
            Compressor::Deflate(algorithm) => algorithm.write_to(writer, bytes),
            Compressor::Packbits(algorithm) => algorithm.write_to(writer, bytes),
        }
    }
}

#[cfg(test)]
mod tests {
    pub const TEST_DATA: &[u8] = b"This is a string for checking various compression algorithms.";
}