Coverage Report

Created: 2024-12-17 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/deflate-1.0.0/src/compression_options.rs
Line
Count
Source (jump to first uncovered line)
1
//! This module contains the various options to tweak how compression is performed.
2
//!
3
//! Note that due to the nature of the `DEFLATE` format, lower compression levels
4
//! may for some data compress better than higher compression levels.
5
//!
6
//! For applications where a maximum level of compression (irrespective of compression
7
//! speed) is required, consider using the [`Zopfli`](https://crates.io/crates/zopfli)
8
//! compressor, which uses a specialised (but slow) algorithm to figure out the maximum
9
//! of compression for the provided data.
10
//!
11
use crate::lz77::MatchingType;
12
use std::convert::From;
13
14
pub const HIGH_MAX_HASH_CHECKS: u16 = 1768;
15
pub const HIGH_LAZY_IF_LESS_THAN: u16 = 128;
16
/// The maximum number of hash checks that make sense as this is the length
17
/// of the hash chain.
18
pub const MAX_HASH_CHECKS: u16 = 32 * 1024;
19
pub const DEFAULT_MAX_HASH_CHECKS: u16 = 128;
20
pub const DEFAULT_LAZY_IF_LESS_THAN: u16 = 32;
21
22
/// An enum describing the level of compression to be used by the encoder
23
///
24
/// Higher compression ratios will take longer to encode.
25
///
26
/// This is a simplified interface to specify a compression level.
27
///
28
/// [See also `CompressionOptions`](./struct.CompressionOptions.html) which provides for
29
/// tweaking the settings more finely.
30
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
31
pub enum Compression {
32
    /// Fast minimal compression (`CompressionOptions::fast()`).
33
    Fast,
34
    /// Default level (`CompressionOptions::default()`).
35
    Default,
36
    /// Higher compression level (`CompressionOptions::high()`).
37
    ///
38
    /// Best in this context isn't actually the highest possible level
39
    /// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
40
    /// library.
41
    Best,
42
}
43
44
impl Default for Compression {
45
0
    fn default() -> Compression {
46
0
        Compression::Default
47
0
    }
48
}
49
50
/// Enum allowing some special options (not implemented yet)!
51
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
52
pub enum SpecialOptions {
53
    /// Compress normally.
54
    Normal,
55
    /// Force fixed Huffman tables. (Unimplemented!).
56
    _ForceFixed,
57
    /// Force stored (uncompressed) blocks only. (Unimplemented!).
58
    _ForceStored,
59
}
60
61
impl Default for SpecialOptions {
62
0
    fn default() -> SpecialOptions {
63
0
        SpecialOptions::Normal
64
0
    }
65
}
66
67
pub const DEFAULT_OPTIONS: CompressionOptions = CompressionOptions {
68
    max_hash_checks: DEFAULT_MAX_HASH_CHECKS,
69
    lazy_if_less_than: DEFAULT_LAZY_IF_LESS_THAN,
70
    matching_type: MatchingType::Lazy,
71
    special: SpecialOptions::Normal,
72
};
73
74
/// A struct describing the options for a compressor or compression function.
75
///
76
/// These values are not stable and still subject to change!
77
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
78
pub struct CompressionOptions {
79
    /// The maximum number of checks to make in the hash table for matches.
80
    ///
81
    /// Higher numbers mean slower, but better compression. Very high (say `>1024`) values
82
    /// will impact compression speed a lot. The maximum match length is 2^15, so values higher than
83
    /// this won't make any difference, and will be truncated to 2^15 by the compression
84
    /// function/writer.
85
    ///
86
    /// Default value: `128`
87
    pub max_hash_checks: u16,
88
    // pub _window_size: u16,
89
    /// Only lazy match if we have a length less than this value.
90
    ///
91
    /// Higher values degrade compression slightly, but improve compression speed.
92
    ///
93
    /// * `0`: Never lazy match. (Same effect as setting `MatchingType` to greedy, but may be slower).
94
    /// * `1...257`: Only check for a better match if the first match was shorter than this value.
95
    /// * `258`: Always lazy match.
96
    ///
97
    /// As the maximum length of a match is `258`, values higher than this will have
98
    /// no further effect.
99
    ///
100
    /// * Default value: `32`
101
    pub lazy_if_less_than: u16,
102
103
    // pub _decent_match: u16,
104
    /// Whether to use lazy or greedy matching.
105
    ///
106
    /// Lazy matching will provide better compression, at the expense of compression speed.
107
    ///
108
    /// As a special case, if max_hash_checks is set to 0, and matching_type is set to lazy,
109
    /// compression using only run-length encoding (i.e maximum match distance of 1) is performed.
110
    /// (This may be changed in the future but is defined like this at the moment to avoid API
111
    /// breakage.
112
    ///
113
    /// [See `MatchingType`](./enum.MatchingType.html)
114
    ///
115
    /// * Default value: `MatchingType::Lazy`
116
    pub matching_type: MatchingType,
117
    /// Force fixed/stored blocks (Not implemented yet).
118
    /// * Default value: `SpecialOptions::Normal`
119
    pub special: SpecialOptions,
120
}
121
122
// Some standard profiles for the compression options.
123
// Ord should be implemented at some point, but won't yet until the struct is stabilised.
124
impl CompressionOptions {
125
    /// Returns compression settings roughly corresponding to the `HIGH(9)` setting in miniz.
126
0
    pub const fn high() -> CompressionOptions {
127
0
        CompressionOptions {
128
0
            max_hash_checks: HIGH_MAX_HASH_CHECKS,
129
0
            lazy_if_less_than: HIGH_LAZY_IF_LESS_THAN,
130
0
            matching_type: MatchingType::Lazy,
131
0
            special: SpecialOptions::Normal,
132
0
        }
133
0
    }
134
135
    /// Returns  a fast set of compression settings
136
    ///
137
    /// Ideally this should roughly correspond to the `FAST(1)` setting in miniz.
138
    /// However, that setting makes miniz use a somewhat different algorithm,
139
    /// so currently hte fast level in this library is slower and better compressing
140
    /// than the corresponding level in miniz.
141
0
    pub const fn fast() -> CompressionOptions {
142
0
        CompressionOptions {
143
0
            max_hash_checks: 1,
144
0
            lazy_if_less_than: 0,
145
0
            matching_type: MatchingType::Greedy,
146
0
            special: SpecialOptions::Normal,
147
0
        }
148
0
    }
149
150
    /// Returns a set of compression settings that makes the compressor only compress using
151
    /// Huffman coding. (Ignoring any length/distance matching)
152
    ///
153
    /// This will normally have the worst compression ratio (besides only using uncompressed data),
154
    /// but may be the fastest method in some cases.
155
0
    pub const fn huffman_only() -> CompressionOptions {
156
0
        CompressionOptions {
157
0
            max_hash_checks: 0,
158
0
            lazy_if_less_than: 0,
159
0
            matching_type: MatchingType::Greedy,
160
0
            special: SpecialOptions::Normal,
161
0
        }
162
0
    }
163
164
    /// Returns a set of compression settings that makes the compressor compress only using
165
    /// run-length encoding (i.e only looking for matches one byte back).
166
    ///
167
    /// This is very fast, but tends to compress worse than looking for more matches using hash
168
    /// chains that the slower settings do.
169
    /// Works best on data that has runs of equivalent bytes, like binary or simple images,
170
    /// less good for text.
171
0
    pub const fn rle() -> CompressionOptions {
172
0
        CompressionOptions {
173
0
            max_hash_checks: 0,
174
0
            lazy_if_less_than: 0,
175
0
            matching_type: MatchingType::Lazy,
176
0
            special: SpecialOptions::Normal,
177
0
        }
178
0
    }
179
}
180
181
impl Default for CompressionOptions {
182
    /// Returns the options describing the default compression level.
183
0
    fn default() -> CompressionOptions {
184
0
        DEFAULT_OPTIONS
185
0
    }
186
}
187
188
impl From<Compression> for CompressionOptions {
189
0
    fn from(compression: Compression) -> CompressionOptions {
190
0
        match compression {
191
0
            Compression::Fast => CompressionOptions::fast(),
192
0
            Compression::Default => CompressionOptions::default(),
193
0
            Compression::Best => CompressionOptions::high(),
194
        }
195
0
    }
196
}