zstd_complete/encoding/
compression_level.rs1use core::{convert::TryFrom, fmt};
2
3#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9pub struct CompressionLevel(i32);
10
11impl CompressionLevel {
12 pub const UNCOMPRESSED: Self = Self(0);
14 pub const FASTEST: Self = Self(1);
16 pub const DEFAULT: Self = Self(3);
18 pub const BETTER: Self = Self(7);
20 pub const BEST: Self = Self(11);
22 pub const MAXIMUM: Self = Self(22);
24
25 #[allow(non_upper_case_globals)]
27 pub const Uncompressed: Self = Self::UNCOMPRESSED;
28 #[allow(non_upper_case_globals)]
29 pub const Fastest: Self = Self::FASTEST;
30 #[allow(non_upper_case_globals)]
31 pub const Default: Self = Self::DEFAULT;
32 #[allow(non_upper_case_globals)]
33 pub const Better: Self = Self::BETTER;
34 #[allow(non_upper_case_globals)]
35 pub const Best: Self = Self::BEST;
36
37 pub const MAX_FAST_ACCELERATION: u32 = 128 * 1024;
39
40 pub const fn new(level: u8) -> Result<Self, InvalidCompressionLevel> {
42 if level >= 1 && level as i32 <= Self::MAXIMUM.0 {
43 Ok(Self(level as i32))
44 } else {
45 Err(InvalidCompressionLevel {
46 level: level as i32,
47 })
48 }
49 }
50
51 pub const fn fast(acceleration: u32) -> Result<Self, InvalidCompressionLevel> {
54 if acceleration >= 1 && acceleration <= Self::MAX_FAST_ACCELERATION {
55 Ok(Self(-(acceleration as i32)))
56 } else {
57 Err(InvalidCompressionLevel {
58 level: if acceleration > i32::MAX as u32 {
59 i32::MIN
60 } else {
61 -(acceleration as i32)
62 },
63 })
64 }
65 }
66
67 pub const fn get(self) -> i32 {
69 self.0
70 }
71
72 pub(crate) const fn c_level(self) -> i32 {
73 self.0
74 }
75
76 pub(crate) const fn is_uncompressed(self) -> bool {
77 self.0 == Self::UNCOMPRESSED.0
78 }
79
80 pub(crate) const fn uses_fastest_legacy_profile(self) -> bool {
81 self.0 == Self::FASTEST.0
82 }
83
84 pub(crate) const fn uses_best_legacy_profile(self) -> bool {
85 self.0 >= Self::BEST.0
86 }
87}
88
89impl Default for CompressionLevel {
90 fn default() -> Self {
91 Self::DEFAULT
92 }
93}
94
95impl TryFrom<i32> for CompressionLevel {
96 type Error = InvalidCompressionLevel;
97
98 fn try_from(level: i32) -> Result<Self, Self::Error> {
99 if (-(Self::MAX_FAST_ACCELERATION as i32)..=-1).contains(&level)
100 || (1..=Self::MAXIMUM.0).contains(&level)
101 {
102 Ok(Self(level))
103 } else {
104 Err(InvalidCompressionLevel { level })
105 }
106 }
107}
108
109impl From<CompressionLevel> for i32 {
110 fn from(level: CompressionLevel) -> Self {
111 level.c_level()
112 }
113}
114
115#[derive(Clone, Copy, Debug, Eq, PartialEq)]
118pub struct InvalidCompressionLevel {
119 level: i32,
120}
121
122impl InvalidCompressionLevel {
123 pub const fn level(self) -> i32 {
125 self.level
126 }
127}
128
129impl fmt::Display for InvalidCompressionLevel {
130 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
131 write!(
132 formatter,
133 "compression level {} is outside -131072..=-1 or 1..=22",
134 self.level,
135 )
136 }
137}
138
139#[cfg(feature = "std")]
140impl std::error::Error for InvalidCompressionLevel {}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145
146 #[test]
147 fn precise_levels_validate_the_public_range() {
148 assert_eq!(CompressionLevel::new(1).unwrap().get(), 1);
149 assert_eq!(CompressionLevel::new(22).unwrap().get(), 22);
150 assert_eq!(CompressionLevel::new(0).unwrap_err().level(), 0);
151 assert_eq!(CompressionLevel::new(23).unwrap_err().level(), 23);
152 assert_eq!(CompressionLevel::fast(1).unwrap().get(), -1);
153 assert_eq!(CompressionLevel::fast(100).unwrap().get(), -100);
154 assert_eq!(
155 CompressionLevel::try_from(-131_072).unwrap().get(),
156 -131_072
157 );
158 assert_eq!(
159 CompressionLevel::try_from(-131_073).unwrap_err().level(),
160 -131_073
161 );
162 assert_eq!(CompressionLevel::fast(0).unwrap_err().level(), 0);
163 }
164
165 #[test]
166 fn named_levels_map_to_expected_values() {
167 assert_eq!(CompressionLevel::FASTEST.get(), 1);
168 assert_eq!(CompressionLevel::DEFAULT.get(), 3);
169 assert_eq!(CompressionLevel::BETTER.get(), 7);
170 assert_eq!(CompressionLevel::BEST.get(), 11);
171 assert_eq!(CompressionLevel::MAXIMUM.get(), 22);
172 }
173}