Skip to main content

use_compression/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4//! Compression level and intent primitives for `RustUse`.
5
6#[cfg(feature = "brotli")]
7pub use use_brotli as brotli;
8#[cfg(feature = "bzip2")]
9pub use use_bzip2 as bzip2;
10#[cfg(feature = "gzip")]
11pub use use_gzip as gzip;
12#[cfg(feature = "lz4")]
13pub use use_lz4 as lz4;
14#[cfg(feature = "xz")]
15pub use use_xz as xz;
16#[cfg(feature = "zstd")]
17pub use use_zstd as zstd;
18
19/// Generic compression level labels.
20#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
21pub enum CompressionLevel {
22    /// Prefer fastest compression.
23    Fastest,
24    /// Balance speed and compressed size.
25    #[default]
26    Balanced,
27    /// Prefer best compressed size.
28    Best,
29    /// Caller-specified numeric compression level.
30    Numeric(u32),
31}
32
33impl CompressionLevel {
34    /// Returns a stable lowercase label.
35    #[must_use]
36    pub const fn as_str(self) -> &'static str {
37        match self {
38            Self::Fastest => "fastest",
39            Self::Balanced => "balanced",
40            Self::Best => "best",
41            Self::Numeric(_) => "numeric",
42        }
43    }
44
45    /// Returns the numeric level when this is [`CompressionLevel::Numeric`].
46    #[must_use]
47    pub const fn numeric(self) -> Option<u32> {
48        match self {
49            Self::Numeric(level) => Some(level),
50            Self::Fastest | Self::Balanced | Self::Best => None,
51        }
52    }
53}
54
55/// Intent behind a compression choice.
56#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
57pub enum CompressionIntent {
58    /// Prefer compression speed.
59    Speed,
60    /// Prefer compressed size.
61    Size,
62    /// Balance speed and size.
63    #[default]
64    Balanced,
65    /// Prefer compatibility with broad tooling.
66    Compatibility,
67}
68
69impl CompressionIntent {
70    /// Returns a stable lowercase label.
71    #[must_use]
72    pub const fn as_str(self) -> &'static str {
73        match self {
74            Self::Speed => "speed",
75            Self::Size => "size",
76            Self::Balanced => "balanced",
77            Self::Compatibility => "compatibility",
78        }
79    }
80}
81
82/// Generic compression settings metadata.
83#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
84pub struct CompressionSettings {
85    /// Compression level label.
86    pub level: CompressionLevel,
87    /// Compression intent label.
88    pub intent: CompressionIntent,
89}
90
91impl CompressionSettings {
92    /// Creates compression settings metadata.
93    #[must_use]
94    pub const fn new(level: CompressionLevel, intent: CompressionIntent) -> Self {
95        Self { level, intent }
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::{CompressionIntent, CompressionLevel, CompressionSettings};
102
103    #[test]
104    fn describes_level_and_intent() {
105        let settings =
106            CompressionSettings::new(CompressionLevel::Numeric(9), CompressionIntent::Size);
107
108        assert_eq!(settings.level.as_str(), "numeric");
109        assert_eq!(settings.level.numeric(), Some(9));
110        assert_eq!(settings.intent.as_str(), "size");
111    }
112
113    #[cfg(all(
114        feature = "bzip2",
115        feature = "brotli",
116        feature = "gzip",
117        feature = "lz4"
118    ))]
119    #[test]
120    fn exposes_codec_namespaces() {
121        assert!(super::bzip2::is_bzip2_filename("bundle.tar.bz2"));
122        assert!(super::brotli::is_brotli_filename("bundle.tar.br"));
123        assert_eq!(super::gzip::GZIP_EXTENSION, "gz");
124        assert!(super::lz4::is_lz4_filename("bundle.tar.lz4"));
125    }
126}