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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
//! The interface and implementations of LZ77 compression algorithm. //! //! LZ77 is a compression algorithm used in [DEFLATE](https://tools.ietf.org/html/rfc1951). pub use self::default::DefaultLz77Encoder; mod default; /// Maximum length of sharable bytes in a pointer. pub const MAX_LENGTH: u16 = 258; /// Maximum backward distance of a pointer. pub const MAX_DISTANCE: u16 = 32768; /// Maximum size of a sliding window. pub const MAX_WINDOW_SIZE: u16 = MAX_DISTANCE; /// A LZ77 encoded data. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Code { /// Literal byte. Literal(u8), /// Backward pointer to shared data. Pointer { /// Length of the shared data. /// The values must be limited to `MAX_LENGTH`. length: u16, /// Distance between current position and start position of the shared data. /// The values must be limited to `MAX_DISTANCE`. backward_distance: u16, }, } /// Compression level. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum CompressionLevel { /// No compression. None, /// Best speed. Fast, /// Balanced between speed and size. Balance, /// Best compression. Best, } /// The `Sink` trait represents a consumer of LZ77 encoded data. pub trait Sink { /// Consumes a LZ77 encoded `Code`. fn consume(&mut self, code: Code); } impl<'a, T> Sink for &'a mut T where T: Sink { fn consume(&mut self, code: Code) { (*self).consume(code); } } /// The `LZ77Encode` trait defines the interface of LZ77 encoding algorithm. pub trait Lz77Encode { /// Encodes a buffer and writes result LZ77 codes to `sink`. fn encode<S>(&mut self, buf: &[u8], sink: S) where S: Sink; /// Flushes the encoder, ensuring that all intermediately buffered codes are consumed by `sink`. fn flush<S>(&mut self, sink: S) where S: Sink; /// Returns the compression level of the encoder. /// /// If the implementation is omitted, `CompressionLevel::Balance` will be returned. fn compression_level(&self) -> CompressionLevel { CompressionLevel::Balance } /// Returns the window size of the encoder. /// /// If the implementation is omitted, `MAX_WINDOW_SIZE` will be returned. fn window_size(&self) -> u16 { MAX_WINDOW_SIZE } } /// A no compression implementation of `LZ77Encode` trait. #[derive(Debug)] pub struct NoCompressionLz77Encoder; impl NoCompressionLz77Encoder { /// Makes a new encoder instance. /// /// # Examples /// ``` /// use libflate::deflate; /// use libflate::lz77::{Lz77Encode, NoCompressionLz77Encoder, CompressionLevel}; /// /// let lz77 = NoCompressionLz77Encoder::new(); /// assert_eq!(lz77.compression_level(), CompressionLevel::None); /// /// let options = deflate::EncodeOptions::with_lz77(lz77); /// let _deflate = deflate::Encoder::with_options(Vec::new(), options); /// ``` pub fn new() -> Self { NoCompressionLz77Encoder } } impl Lz77Encode for NoCompressionLz77Encoder { fn encode<S>(&mut self, buf: &[u8], mut sink: S) where S: Sink { for c in buf.iter().cloned().map(Code::Literal) { sink.consume(c); } } #[allow(unused_variables)] fn flush<S>(&mut self, sink: S) where S: Sink {} fn compression_level(&self) -> CompressionLevel { CompressionLevel::None } }