zstd_complete/encoding/
compression_level.rs1use core::{convert::TryFrom, fmt};
2
3#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9pub struct CompressionLevel(u8);
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 fn new(level: u8) -> Result<Self, InvalidCompressionLevel> {
39 if level >= 1 && level <= Self::MAXIMUM.0 {
40 Ok(Self(level))
41 } else {
42 Err(InvalidCompressionLevel {
43 level: level as i32,
44 })
45 }
46 }
47
48 pub const fn get(self) -> u8 {
50 self.0
51 }
52
53 pub(crate) const fn c_level(self) -> i32 {
54 self.0 as i32
55 }
56
57 pub(crate) const fn is_uncompressed(self) -> bool {
58 self.0 == Self::UNCOMPRESSED.0
59 }
60
61 pub(crate) const fn uses_fastest_legacy_profile(self) -> bool {
62 self.0 == Self::FASTEST.0
63 }
64
65 pub(crate) const fn uses_best_legacy_profile(self) -> bool {
66 self.0 >= Self::BEST.0
67 }
68}
69
70impl Default for CompressionLevel {
71 fn default() -> Self {
72 Self::DEFAULT
73 }
74}
75
76impl TryFrom<i32> for CompressionLevel {
77 type Error = InvalidCompressionLevel;
78
79 fn try_from(level: i32) -> Result<Self, Self::Error> {
80 let level = u8::try_from(level).map_err(|_| InvalidCompressionLevel { level })?;
81 Self::new(level).map_err(|_| InvalidCompressionLevel {
82 level: i32::from(level),
83 })
84 }
85}
86
87impl From<CompressionLevel> for i32 {
88 fn from(level: CompressionLevel) -> Self {
89 level.c_level()
90 }
91}
92
93#[derive(Clone, Copy, Debug, Eq, PartialEq)]
95pub struct InvalidCompressionLevel {
96 level: i32,
97}
98
99impl InvalidCompressionLevel {
100 pub const fn level(self) -> i32 {
102 self.level
103 }
104}
105
106impl fmt::Display for InvalidCompressionLevel {
107 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
108 write!(
109 formatter,
110 "compression level {} is outside the supported range 1..=22",
111 self.level
112 )
113 }
114}
115
116#[cfg(feature = "std")]
117impl std::error::Error for InvalidCompressionLevel {}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn precise_levels_validate_the_public_range() {
125 assert_eq!(CompressionLevel::new(1).unwrap().get(), 1);
126 assert_eq!(CompressionLevel::new(22).unwrap().get(), 22);
127 assert_eq!(CompressionLevel::new(0).unwrap_err().level(), 0);
128 assert_eq!(CompressionLevel::new(23).unwrap_err().level(), 23);
129 }
130
131 #[test]
132 fn named_levels_map_to_expected_values() {
133 assert_eq!(CompressionLevel::FASTEST.get(), 1);
134 assert_eq!(CompressionLevel::DEFAULT.get(), 3);
135 assert_eq!(CompressionLevel::BETTER.get(), 7);
136 assert_eq!(CompressionLevel::BEST.get(), 11);
137 assert_eq!(CompressionLevel::MAXIMUM.get(), 22);
138 }
139}